多次发请求优化为发一次请求

优化 getUserInfo 请求

要求

getUserInfo 是个通用接口,在各个模块里面都有可能使用 requestUserInfo 模拟的是请求服务端真正获取用户信息的方法

业务背景

  • 在一个页面有 A, B, C 等多个功能模块,A, B, C 模块渲染执行顺序不可控
  • 每个模块都会调用 getUserInfo 这个方法, 这个方法是可以直接调用 requestUserInfo 获取用户信息
  • 调用三次就会发起三次网络请求
  • 现在需要优化 getUserInfo 这个方法, 保证 getUserInfo 方法3次调用后, 最终只会发出一次网络请求。

测试用例

ts 复制代码
import { isEqual } from 'lodash-es';

/**
 * 第二题
 */

// 核心用户请求
let _requestTime = 0;
const requestUserInfo = () => {
  // 这个方法的实现不能修改
  return Promise.resolve().then(() => {
    return new Promise<void>((resolve) => {
      setTimeout(() => {
        // 模拟 ajax 异步,1s 返回
        resolve();
      }, 1000);
    }).then(() => {
      _requestTime++;
      return {
        nick: "nick",
        age: "18",
      };
    });
  });
};

async () => {
  try {
    // 模拟请求
    const result = await Promise.all([
      getUserInfo(),
      new Promise(resolve => setTimeout(async () => { resolve(await getUserInfo()) }, 300)),
      new Promise(resolve => setTimeout(async () => { resolve(await getUserInfo()) }, 2300))]);
    if (
      !isEqual(result, [{
        nick: "nick",
        age: "18",
      }, {
        nick: "nick",
        age: "18",
      }, {
        nick: "nick",
        age: "18",
      }])
    ) {
      throw new Error('Wrong answer');
    }
    return _requestTime === 1;
  } catch (err) {
    console.warn('测试运行失败');
    console.error(err);
    return false;
  }
};

思路

  • 由于测试用例使用Promise.all调用,则需要返回Promise。
  • 又因为只需要调用一次接口则拿到数据之后需要缓存方便共享。
  • 一旦有数据那就直接resolve。
  • 由于Promise返回的也是Promise,可以缓存第一次的Promise,如果存在则只需要等第一次结束
  • 结束之后的Promise我们再通过拿到结果进行resolve。

实现

js 复制代码
let cache = null;
let preRequest = null;
const getUserInfo = () => {
  return new Promise((resolve,reject)=>{
    if(cache) resolve(cache)
    if(preRequest){
      preRequest.then(res=>{
        resolve(cache)
      }).catch(err=>{
        reject(cache)
      })
    }else{
      preRequest = requestUserInfo().then(res => {
        cache = res;
        resolve(res)
      }).catch((err) => {
        reject(err)
      })
    }
  })
}
相关推荐
蟾宫曲4 小时前
在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
前端·npm·vue3·vite·element-plus·计时器
秋雨凉人心4 小时前
简单发布一个npm包
前端·javascript·webpack·npm·node.js
liuxin334455664 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
qq13267029405 小时前
运行Zr.Admin项目(前端)
前端·vue2·zradmin前端·zradmin vue·运行zradmin·vue2版本zradmin
LCG元6 小时前
Vue.js组件开发-使用vue-pdf显示PDF
vue.js
魏时烟6 小时前
css文字折行以及双端对齐实现方式
前端·css
哥谭居民00017 小时前
将一个组件的propName属性与父组件中的variable变量进行双向绑定的vue3(组件传值)
javascript·vue.js·typescript·npm·node.js·css3
烟波人长安吖~7 小时前
【目标跟踪+人流计数+人流热图(Web界面)】基于YOLOV11+Vue+SpringBoot+Flask+MySQL
vue.js·pytorch·spring boot·深度学习·yolo·目标跟踪
踢足球的,程序猿7 小时前
Android native+html5的混合开发
javascript
2401_882726487 小时前
低代码配置式组态软件-BY组态
前端·物联网·低代码·前端框架·编辑器·web