http请求缓存

2023-05-30 11:00:10 浏览数 (1)

思路:

  1. 定义一个http的状态map,存储请求的pending和complete,目的是为了解决同一个请求,在同一时间发起多次请求,为了避免发起多次同一个接口,存储status,本次request尚未【success】(非error),不发起下一次同一接口
  2. 定义回调的map,存储请求的回调函数,目的是为了,请求成功之后,触发回调,尤其是同一时间发起多次同一个request,当一个pending时,其他均置于map回调中,当success时,以此触发每个回调
  3. 定义一个返回值map,存储每个request的结果,当下一次发起同一个请求时,去缓存里查找同时返回对应的结果,如果未查到,则发起请求
  4. 定义请求的id,以参数、url以及请求方式当id,以此判断这次请求在缓存中是否有这个id
代码语言:javascript复制
import { singleton  } from "./singleton";

class Cache {
    statusMap = new Map();
    cacheMap = new Map();
    cbMap = new Map();

    constructor() {
    }
    setCache(request) {
        const cacheKey = this.guidGeneratorRequestKey(request);
        if (this.statusMap.has(cacheKey)) {
            const status = this.statusMap.get(cacheKey);
            if (status === 'complete') {
                return Promise.resolve(this.cacheMap.get(cacheKey));
            }
            if (status === 'pending') {
                return new Promise((resolve, reject) => {
                    if (this.cbMap.has(cacheKey)) {
                        const arr = this.cbMap.get(cacheKey);
                        arr.push({
                            onSuccess: resolve,
                            onFail: reject,
                        })
                        this.cbMap.set(cacheKey, arr)
                    } else {
                        this.cbMap.set(cacheKey, [
                            {
                                onSuccess: resolve,
                                onFail: reject,
                            }
                        ])
                    }
                })
            }
        }
        this.statusMap.set(cacheKey, 'pending');
        return new Promise((resolve, reject) => {
            xx({
                url: request.url,
                method: request.method || 'get',
                header: {

                },
                data: request.params,
                timeout: 10000,
                success: (res) => {
                    console.log('[cache]: params, url, res--setCache:', request.params, request.url, res);
                    const token = res.data.data || '';
                    if (res.status == 200 || res.statusCode == 200) { // iOS: status;Android:statusCode
                        this.statusMap.set(cacheKey, 'complete');
                        this.cacheMap.set(cacheKey, token);
                        resolve(token);
                    } else {
                        this.statusMap.delete(cacheKey)
                        reject(res);
                    }
                    if (this.cbMap.has(cacheKey)) {
                        const arr = this.cbMap.get(cacheKey);
                        for (let list of arr) {
                            list.onSuccess && list.onSuccess(token);
                        }
                        this.cbMap.delete(cacheKey)
                    }
                },
                failure: (error) => {
                    console.error('[cache]: error--setCache:', error);
                    reject(error);
                },
            });
        })
    }
    guidGeneratorRequestKey(config) {
        return `url=${ config.url }&method=${ config.method }&params=${ JSON.stringify(config.params) }`;
    }

}

export default singleton(Cache);

以上为基本demo,,此方法有几处待优化:

  1. 成功回调应返回data,而不是data中的某个字段(本方法为解决每次请求接口都会请求token接口而封装,故只返回了token而已)
  2. 上文提及到,同一时间发起多次同一接口,除第一个真正发起了http请求,其余均被推到回调cache中,问题是,如果第一次请求超时,或者报错,进而导致后续http均不会收到数据,所以该方法应该有重试功能
  3. 在这里没有考虑并发问题,应该考虑下,同时发起大量http请求的问题

上述2、3问题,时间关系,后续优化~

0 人点赞