当前位置 主页 > 网站技术 > 代码类 >

    微信小程序中网络请求缓存的解决方法

    栏目:代码类 时间:2019-12-29 15:07

    需求

    提交小程序审核时,有一个体验测评,产品让我们根据小程序的体验测评报告去优化小程序。

    其中有一项是网络请求的优化,给我们出了很大的难题。

    文档中是这样解释的:3分钟以内同一个url请求不出现两次回包大于128KB且一模一样的内容

    看到这个问题的时候,首先想到的是在响应头上加上cache-control,经过测试发现小程序并不支持网路请求缓存。搜索发现官方明确答复,小程序不支持网络请求缓存:wx.request不支持http缓存

    既然官方不支持网络请求缓存,那只能自己想办法解决这个问题了。

    先来看一下需求:3分钟内,同一请求只能请求一次。

    分析

    分析:

    只需做GET请求的网络缓存。 缓存时间如何控制。 做了缓存之后,如何知道3分钟,这个请求在服务端数据有没更新。 提交GET请求前,先检查本地有没有缓存

    前两点比较好实现,虽然小程序不支持网络请求缓存,但我们还是可以利用cache-control来实现这个功能。

    首先网络请求需不需要情缓存统一交给服务端去做,服务端在处理GET请求时,统一加上响应头cache-control,如果需要缓存就用max-age=180,如果不需要做网络请求就用no-cache。前端根据响应头信息自己做前端缓存。

    其中的难点是前端如何知道服务端数据有没更新,如果服务端数据更新了,前端还是使用缓存这是有问题的。

    经过一番思考后发现,前端提交数据后,相应的GET请求数据会更新,也就是说前端只要有数据提交,就应该把缓存清空。

    这有一个难点,当前端提交数据时,前端是不知道哪些GET请求会因此更新数据,所以这个问题我们没有解决,我的方法比较粗暴:只要前端提交了数据,就将所有缓存清空。这是一个治标不治本的问题。

    实现

    公司项目封装了HTTP请求

    拦截请求,如果是GET请求,检查缓存,

    如果缓存没过期,将缓存返回出去,不再发请求 如果缓存过期,发请求
    if (request.method.toLowerCase() === "get"){
     // param 请求信息
     const cache = this.handleCatchControl(request)
     if (!cache.isRequest)
     return this.listener.onApiResponse(request, 200, cache.data), sequence; //将缓存返回给对应的请求
    }

    缓存网络请求

    // param 响应头,上下文,响应数据
    this.setCatchControl(headers, context, response.data)

    两个工具函数

    处理网络缓存 设置网络缓存

    设置网络请求

    GET请求缓存数据,其他请求清空数据 数据格式:
    //如果同时发起多个`GET`请求,需要拼接之前缓存数据
    ApiAgent.cacheData = Object.assign(ApiAgent.cacheData,{
     [context.request.url]: { //api
     data, //响应数据
     expireTime: Number(cacheControl.split("=")[1] + '000'), //过期时间
     cacheTime: new Date().getTime(), //缓存时间
     }
    })
    // param 响应头,上下文,响应数据
    setCatchControl(responseHeader: any, context: any, data: any) {
     if (context.request.method.toLowerCase() === "get") {
     const headers = HandleHeaders.get(responseHeader)
     const cacheControl = headers["cache-control"]
     if (cacheControl && cacheControl !== "no-cache") {
      ApiAgent.cacheData = Object.assign(ApiAgent.cacheData,{
      [context.request.url]: {
       data,
       expireTime: Number(cacheControl.split("=")[1] + '000'),
       cacheTime: new Date().getTime(),
      }
      })
     }
     } else {
     ApiAgent.cacheData = {}
     }
    }