CacheManager.addRule

基础库 2.24.0 开始支持,低版本需做兼容处理。

微信小程序插件:不支持

相关文档: 弱网体验优化

功能描述

添加规则。

参数

string|RegExp|Record. rule

规则

返回值

string

规则 id

规则说明

支持的规则写法有字符串、正则和对象三种:

字符串写法

  1. addRule('/abc'):纯 uri 串。
  2. `addRule(‘GET /abc’):带方法的 uri 串,除了匹配 uri 外,还会匹配请求方法。如例子中必须是 GET 方法请求才会被匹配。
  3. addRule('/abc/:id'):带可变部分的 uri 串,id 可以是任意符合标准的字符串,表示这一段可以动态变化。比如/abc/123和/abc/321都会被匹配,而/abc/123/xxx` 因为多了一段,就不会被匹配。
  4. addRule('/abc?aa'):带 query 参数的 uri 串,包含 aa 参数,值可以为任意值。比如/abc?aa=haha会被匹配,但是/abc就不会被匹配,因为缺少规则中声明的 aa 参数;不过如果请求是/abc?aa=haha&bb=123`,虽然多带了 bb 参数,但是因为包含了 aa 参数,所以也可以被匹配。
  5. addRule('/abc?dd=haha'):带 query 参数的 uri 串,包含 dd 参数且值为 haha。比如/abc?dd=haha和/abc?dd=haha&bb=123会被匹配,而/abc?dd=123` 就不会被匹配,因为规则要求了 dd 参数的值。

以上写法中的 uri 串如果只有 path 部分,则会取全局 origin 进行补全。比如全局 origin 是 https://weixin.qq.com,而规则是 /abc,则会补全为 https://weixin.qq.com/abc。因此在前面例子中 addRule('/abc') 和 addRule('https://weixin.qq.com/abc') 的写法效果一致。所以一般情况下如果需要匹配的请求 origin 和全局 origin 一致,则规则中可忽略不写 orign。

正则写法

  1. addRule(/\/(abc|cba)$/ig):直接正则匹配请求的 uri,同时会比对请求 origin 和全局 origin 是否一致。
  2. addRule(/^https:\/\/weixin.qq.com\/(abc|cba)$/ig):带有 orign 部分的正则表达式,则只匹配 uri,不再比对 origin。

对象写法

使用规则对象,可以更为详细的描述规则内容。(一般使用规则对象,是为了匹配请求参数)

规则对象:

属性名 类型 默认值 备注
id string 规则 id,如果不填则会由基础库生成
method string 请求方法,可选值 GET/POST/PATCH/PUT/DELETE,如果为空则表示前面提到的所有方法都能被匹配到
url any 必填 uri 匹配规则,可参考规则字符串写法和正则写法
maxAge number 7 * 24 * 60 * 60 * 1000 缓存有效时间,单位为 ms,不填则默认取缓存管理器全局的缓存有效时间
dataSchema Array<DataRule> 匹配请求参数

其中,dataSchema 用来匹配对象类型的请求参数(比如 wx.request 的 data),默认可以不填,即不做参数匹配。

dataSchema 的类型是一个 DataRule 对象数组,一个 DataRule 对象描述一个参数,比如一个 wx.request 请求的 data 是 {a: 123, b: 'haha', c: true},你想要用一条规则来匹配其中的 a 和 b 参数,如果 a 是数字且 b 是字符串就能命中该规则,那么就需要在 dataSchema 中补充两个 DataRule 对象,即 [{name: 'a', schema: {type: 'number'}}, {name: 'b', schema: {type: 'string'}}]。

DataRule 对象:

属性名 类型 默认值 备注
name string 需要匹配的参数名
schema DataSchema/Array<DataSchema> 需要匹配的参数模式,支持数组,表示该参数值有多种模式

name 表示要匹配的参数名,schema 为 DataSchema 对象,用来描述该参数的类型和值。

一个 DataRule 对象也可以匹配可能拥有多种类型的参数,所以 schema 也支持为 DataSchema 对象数组。比如上述例子中,希望匹配的 a 参数必须是数值或者字符串,那么可以这么写:{name: 'a', schema: [{type: 'number'}, {type: 'string'}]}。

DataSchema 对象:

属性名 类型 默认值 备注
type string 需要匹配的 data 对象的参数类型,string、number、boolean、null、object、any(表示任意类型),同时支持数组模式(数组模式则在类型后面加 [],如 string[] 表示字符串数组)
value string/regexp/function/Array<DataRule> 需要匹配的 data 对象的参数值,当 type 为基本类型时,可以用 string/regexp 来匹配固定的值,也可以通过 function 来确定值是否匹配,如果传入的 type 是 object,那么表示需要嵌套匹配值是否正确,可以传入 Array

type 参数表示要匹配的参数类型,value 表示要匹配的参数值。其中 value 支持多种写法,不同写法有如下匹配方式:

  1. 字符串写法:直接判值的字符串形式是否和给定字符串一样,比如 value 值为 123,就要求参数值必须为 123 才能与之匹配。
  2. 正则写法:直接判值的字符串形式是否能被正则匹配,比如 value 值为 /\d+/ig,就要求参数值必须为数字,如果参数值为 abc 则不会被匹配。
  3. 函数写法:在匹配时会调用用户传入的函数,交由用户判断是否匹配。
  4. DataRule 数组写法:当参数类型为对象时,那么字符串写法和正则写法就无法使用,需要传入 DataRule 数组来进行匹配,即通过嵌套 DataRule 数组的方式来匹配嵌套的对象。

示例代码

const ruleId = cacheManager.addRule({
  id: 'haha-rule',
  method: 'GET',
  url: '/haha',
  maxAge: 123455,
  dataSchema: [
    // data 字段的匹配,默认为空,表示不匹配
    // 类型可以是:string、number、boolean、null、object、any(表示任意类型均可),以及这些类型的数组表示方式
    {name: 'aaa', schema: {type: 'string'}}, // 类型为 string
    {name: 'bbb', schema: [{type: 'number'}, {type: 'string'}]}, // 类型为 number, string
    {name: 'ccc', schema: {type: 'string', value: 'abc'}}, // 值为 abc
    {name: 'ddd', schema: {type: 'string', value: /(abc|cba)/ig}}, // 值符合该正则匹配,如果该值不是字符串类型,则会被尝试转成字符串后再进行比较
    {name: 'ddd', schema: {type: 'string', value: val => val === '123'}}, // 传入函数来校验值
    {name: 'eee', schema: {type: 'object', value: [{ // 类型为对象,则通过嵌套的方式来逐层校验
      name: 'aaa', schema: {type: 'string'},
      // ...
      // 嵌套 dataSchema,同上面的方式一样来匹配嵌套的对象
    }]}},
    {name: 'fff', schema: {type: 'string[]'}}, // 类型为 string 数组
    {name: 'ggg', schema: {type: 'any'}}, // 类型为任意类型
    {name: 'hhh', schema: {type: 'any[]'}}, // 类型为任意类型的数组
  }],
})

补充说明

用户可以添加多条规则,每条规则都会去解析网络请求,然后判断是否命中规则。假设有多条规则命中,则取第一条命中的规则。

缓存覆盖

不同的网络请求也可能命中同一条规则,所以每条规则可能对应多个缓存。每条规则会有一个规则 id,每个缓存会有一个缓存 id,一个规则 id 可能对应多个缓存 id,而缓存管理器的缓存存储是基于缓存 id 标识的,如果两个不同的请求生成了同样的缓存 id,那么后发生的请求结果缓存会覆盖前者。因此使用时需要思考缓存的覆盖情况,目前缓存 id 生成方式如下:

  1. 规则使用字符串写法:那么按 method + url + 规则中声明的 query 参数来生成缓存 id。

需要注意的是这里不使用真实请求中的 query 参数来生成缓存 id,而是使用规则中匹配到的 query 来生成缓存 id。比如规则是 /abc?aa=123,请求是 GET 方法的 /abc?aa=123&bb=123,那么就会基于 GET /abc?aa=123 来生成缓存 id。而规则里没有声明 bb=123,所以 bb 参数不会被纳入缓存 id 的生成基准。

  1. 规则使用正则写法:那么只按 method + url 生成缓存 id,不考虑 query 参数。
  2. 规则使用对象写法:如果规则对象中的 url 是字符串写法,那么按 method + url + 规则中声明的 query 参数 + 规则中 dataSchema 声明的请求参数来生成缓存 id;如果规则对象中的 url 是正则写法,那么按 method + url + 规则中 dataSchema 声明的请求参数来生成缓存 id。

生成缓存 id 时没有使用请求中完整的 query 参数或者请求参数来作为基准,是考虑到很多请求可能会带上 token 或时间戳等参数。因为此参数存在不确定性,会导致每次请求生成的缓存 id 都不同,进而导致缓存命中率下降,故采取规则中声明的 query 参数和 dataSchema 声明的请求参数来作为生成缓存 id 的基准。

CacheManager

基础库 2.24.0 开始支持,低版本需做兼容处理。

相关文档: 弱网体验优化

缓存管理器。全局只有唯一实例,一旦被创建出来即表示接入缓存管理器。其有以下几个能力:

  1. 在网络通畅时,符合一定规则的用户网络请求(目前只包括普通 wx.request 请求)会被缓存。
  2. 在网络通畅时,某些 wx api 调用会被缓存。
  3. 进入弱网/离线状态时,会提供事件给用户,用户可以决定是否使用缓存返回。
  4. 提供进入和退出弱网/离线状态的事件。
  1. 缓存管理器中涉及的网络请求如无特指,均指普通的 wx.request 异步请求,参数和返回值中均不考虑涉及 ArrayBuffer 或 TypedArray 的情形。
  2. 缓存管理器中的缓存不会占用 storage 空间,但是有大小限制,请勿在非必要的请求上使用缓存。

属性

string mode

当前缓存模式

mode 的合法值

值 说明 最低版本
weakNetwork 默认值,弱网/离线使用缓存返回
always 总是使用缓存返回
none 不开启,后续可手动开启/停止使用缓存返回

string origin

全局 origin

number maxAge

全局缓存有效时间

number state

当前缓存管理器状态

state 的合法值

值 说明 最低版本
0 不使用缓存返回
1 使用缓存返回
2 未知

方法

Array. CacheManager.addRules(Array.<(string|RegExp|Record.)> rules)

批量添加规则,规则写法可参考 CacheManager.addRule。

string CacheManager.addRule(string|RegExp|Record. rule)

添加规则。

CacheManager.deleteRules(Array. ids)

批量删除规则,同时会删除对应规则下所有缓存。

CacheManager.deleteRule(string id)

删除规则,同时会删除对应规则下所有缓存。

CacheManager.clearRules()

清空所有规则,同时会删除对应规则下所有缓存。

CacheManager.on(string eventName, function handler)

监听事件。

CacheManager.off(string eventName, function handler)

取消事件监听。

CacheManager.start()

开启缓存,仅在 mode 为 none 时生效,调用后缓存管理器的 state 会置为 1。

CacheManager.stop()

关闭缓存,仅在 mode 为 none 时生效,调用后缓存管理器的 state 会置为 0。

Object CacheManager.match(Object evt)

匹配命中的缓存规则,一般需要和 request 事件搭配使用。

CacheManager.deleteCaches(Array. ids)

批量删除缓存。

CacheManager.deleteCache(string id)

删除缓存。

CacheManager.clearCaches()

清空所有缓存。

wx.createCacheManager(Object object)

基础库 2.24.0 开始支持,低版本需做兼容处理。

微信小程序插件:不支持

相关文档: 弱网体验优化

功能描述

创建缓存管理器

参数

Object object

属性 类型 默认值 必填 说明
origin string 否 全局 origin
mode string weakNetwork 否 缓存模式
合法值 说明
weakNetwork 弱网/离线使用缓存返回
always 总是使用缓存返回
none 不开启,后续可手动开启/停止使用缓存返回
maxAge number 否 全局缓存有效时间,单位为毫秒,默认为 7 天,最长不超过 30 天
extra object 否 额外的缓存处理
结构属性 类型 默认值 必填 说明
apiList Array.<string> 否 需要缓存的 wx api 接口,不传则表示支持缓存的接口全都做缓存处理。返回的如果是缓存数据,开发者可通过 fromCache 标记区分
合法值 说明
wx.login
wx.checkSession
wx.getSetting

返回值

CacheManager

缓存管理器

示例代码

查看完整示例代码

const cacheManager = createCacheManager()
cacheManager.addRule(/https:\/\/(?:.*)/ig) // 表示所有 https 请求都匹配

cacheManager.on('request', evt => {
 // 在弱网时接收到 wx.request 请求
 return new Promise((resolve, reject) => {
   const matchRes = cm.match(evt)
   if (matchRes && matchRes.data) {
     // 有缓存,返回
     resolve(matchRes.data)
   } else {
     // 没缓存,抛错
     reject({ errMsg: 'no cache' })
   }
 })
})