场景,页面中有多个子模块(如A、B、C),会发送同一个http请求(多个模块发送的http请求参数相同)。这些模块彼此独立,页面中可能有些时候用到A、B模块,有些时候用到B、C模块。模块加载有先后顺序,且不固定,A、B、C模块都有可能第一个加载。

    项目是通过更改Promise chain + cache的模式实现从图1到图2的模式,避免重复发送http请求。
    image.png
    图1 ↑
    image.png
    图2 ↑

    如果是下面的图3到图4,用防抖解决。
    image.png
    图3 ↑
    image.png
    图4 ↑

    实际项目是一个vue项目,由于模块A、B、C互相独立,且层级关系并不同级,在这个场景里,入口页面发一次请求,做数据处理再分发给三个模块这样数据传递模式不合适。

    考虑下来,在vue store(vuex)的actions中发送http请求,处理数据(初加工,加工公共部分),缓存数据(交给vuex state)这种方式,子模块自行取用。

    按照这个思路实现,要解决下面几个问题:
    1、判断是相同的请求。
    2、缓存结果,func1来请求数据时,在缓存中查找结果是否存在;如果结果存在,子模块请求数据时,不再发送第二次http请求。
    3、定时清理缓存。(非必须)

    1、判断相同的请求,最完善的实现方式当然是hash,这里不是本文要讲的重点,略过。
    2、缓存结果,这里的结果不是http请求返回之后的数据,而是http已经发送的状态。

    说明:

    在第一次发送http请求之后,这个http请求的状态(如pending状态的Promise实例)就必须即刻进入缓存中。不能等待请求完成之后,再将http请求的结果放入缓存中。

    如果是等待http完成后将http的结果放入缓存,第1个func1触发http1请求发送未返回结果的阶段,缓存中没有http1的结果。此时如果第2个func1到来,第2个func1依然可以触发http1发送。

    实现:
    直接上代码
    image.png
    image.png
    image.png

    重点在actions中的new Promise操作。还要注意如果http请求失败,要通过DELETE_HTTP_RES操作来清空这个字段。

    完结。

    代码示例见
    https://github.com/DiracKeeko/daily_test/blob/master/0083cacheAndChangePromiseChain.js