当一个请求被多次调用后,如何设计单例模式共享一次调用的结果?

67 阅读1分钟

分享一个朋友问我的问题..

先看下他的代码:

const getSiteInfo = async () => {
    const app = getApp() ?? { globalData: {} };
    if (app.globalData?._siteinfo_?.siteroot) return app.globalData._siteinfo_;
    try {
        const timestamp = Date.now();
        const siteinfoResp = await fly.get(`https://xxx.com/config.json?k=${timestamp}`);
        app.globalData._siteinfo_ = siteinfoResp.data;
        return siteinfoResp.data
    } catch (error) {
        // ...
    }
};

他写了这样一个方法,用于获取远程服务器上的一个json配置文件,所有的请求都会在发起前查询以下是否已经拿到了配置信息,但是在页面打开时,有三个请求同时发起来,这就导致这个方法被调用了三次,但是因为这个json的内容都是一样的,所以多出来的这两个请求就有点多余了,他想怎么样共享一个结果。

这种场景单例模式的设计思路就能很好的解决这个问题,我们将这个请求的prosime缓存起来,后面的请求来了,直接返回这个缓存的prosime即可完成共享。

代码如下:

let siteInfoPromise = null;
const getSiteInfo = async () => {
    const app = getApp() ?? { globalData: {} };
    if (app.globalData?._siteinfo_?.siteroot) return app.globalData._siteinfo_;
    // 如果已经有一个请求在进行,直接返回该请求的Promise
    if (siteInfoPromise) return siteInfoPromise;
    try {
        // 创建一个新的请求Promise
        siteInfoPromise = (async () => {
            const timestamp = Date.now();
            const siteinfoResp = await fly.get(`https://xxx.com/config.json?k=${timestamp}`);
            app.globalData._siteinfo_ = siteinfoResp.data;
            return siteinfoResp.data;
        })();
        // 等待请求完成并返回结果
        return await siteInfoPromise;
    } catch (error) {
        // 清除Promise以便下次调用能重新尝试
        siteInfoPromise = null;	
    }
};

此时我还想到了,其实闭包也可以实现这样的功能。