请教前端缓存 API 接口数据,数据发生变化时,如何告知前端?

场景如下:

在第一次进入 APP 首页的时候,前端请求 index 接口,返回 推荐文章banner秒杀商品推荐商品 等展示数据。


前端请求一次后,将数据缓存到 storage 里面,此时如果 管理后台 将首页推荐文章连接地址修改后,前端这个时候不知道首页数据有更新,没有重新请求 index 接口。

请问这种情况前后端应该如何约定?

我能想到的解决方案是:
进入首页,前端都请求一次 index 接口,向接口传一个 version 参数,此时后端判断如果 version 相同,就不执行查询,返回空。

如果前端传递的 version 参数小于 index 接口的 version 就正常返回数据,并且返回后端当前的 version 参数,前端接收到数据后,将 version 也保存到 storage 中。


不知道我这种思路是不是常规解决方案,如果是的话,后端应该怎么维护 version 这个参数呢?后端怎么知道什么时候应该更新 version
而且 version 参数应该存储在哪里呢?我觉得应该存储在 Cache 中比较好。

请问大家都是怎么处理的?感谢。

悲观者永远正确,乐观者永远前行。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

可以采用 HTTP 协商缓存 ETag 来实现

  1. 在后台每次修改需要缓存的数据时都进行一次 hash(当然你也可以使用其他算法生成唯一标识)

  2. 将接口地址与 hash 值存为键值对

  3. 写一个中间件类如:

    public function handle(Request $request, Closure $next)
    {
        $key = \Cache::get($request->getBaseUrl());
        if ($key && $key === $request->header('If-None-Match')) {
            return \response(null, 304)->header('ETag', $key);
        }
    
        $response = $next($request);
        if ($key) {
            $response->header('ETag', $key);
        }
    
        return $response;
    }
2年前 评论
MArtian (楼主) 2年前
讨论数量: 10

version 在你缓存那些数据变化的时候更新就可以了,可以通过 model 的事件来完成。version 可以存在缓存,数据库只要支持持久存储的任意地方都可以。这算是前端主动获取数据是否更新。 还有一种方式就是 ws,数据变化通过 ws 通知前端数据更新。这种是服务端主动推给前端,实时性更高一些。

2年前 评论

你这个情况感觉首页不适合做缓存吧,除了banner的数据,其他的都有可能发生变化,做缓存反而有问题吧

2年前 评论
leo

首先要确认需求本身是什么?前端加缓存的目的是为了解决什么问题?比如是为了解决用户在弱网场景下请求 banner 接口慢而导致 banner 区域白屏?还是因为服务器带宽有限要节省 API 返回的内容?

2年前 评论
leo (作者) 2年前
MArtian (楼主) 2年前
MArtian (楼主) 2年前

长远来看,还是要用 WS,跟 meteor 一样。地址变了,立即更新,点击就可以了,没有槽点,非常 nice :flushed:

2年前 评论
MArtian (楼主) 2年前

1.用redis去存版本号,为啥,快啊!可以在数据更新的时候顺带着更新版本号,当前端请求接口的时候去redis里找版本号,如果一致就不执行,小于就执行,就不用再去更新了;

2.使用websokect。第一次请求接口的数据肯定是最新的,但是当数据发生变化后,只有重新去请求接口才能知道是否是最新(或者是获取到最新的数据)。因此,使用ws,只要数据一更新,立即推送给所有连接的用户,不需要做任何其他的操作,妥妥的。

2年前 评论
MArtian (楼主) 2年前

每个接口都加个版本控制吧,一个接口专门统一回复这个版本控制状态

2年前 评论

可以采用 HTTP 协商缓存 ETag 来实现

  1. 在后台每次修改需要缓存的数据时都进行一次 hash(当然你也可以使用其他算法生成唯一标识)

  2. 将接口地址与 hash 值存为键值对

  3. 写一个中间件类如:

    public function handle(Request $request, Closure $next)
    {
        $key = \Cache::get($request->getBaseUrl());
        if ($key && $key === $request->header('If-None-Match')) {
            return \response(null, 304)->header('ETag', $key);
        }
    
        $response = $next($request);
        if ($key) {
            $response->header('ETag', $key);
        }
    
        return $response;
    }
2年前 评论
MArtian (楼主) 2年前

为什么不在后端缓存呢

2年前 评论

后端获取数据后缓存,数据变化后清除缓存

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!