优化 requestUserProfile 并发请求
requestUserProfile 是个通用查询用户信息接口,通过传入 uid ,拿用户昵称 在一个支付宝群聊里有 10 多个用户,点击群聊信息,展示各个人的昵称 10 个并发请求,会阻塞接口 10 个依次请求,耗时久,显示昵称太慢 需要优化请求,在并发和耗时之间掌握一个平衡
// 核心用户请求
let _requestTime = 0;
const requestProfile = (uid: string) => {
  // 这个方法的实现不能修改
  return Promise.resolve().then(() => {
    return new Promise<void>((resolve) => {
      setTimeout(() => {
        // 模拟 ajax 异步,1s 返回
        resolve();
      }, 1000);
    }).then(() => {
      _requestTime++;
      return {
        uid,
        nick: `nick-${uid}`,
        age: "18",
      };
    });
  });
};
/**
 *
 * @param uid uid
 * @param max 最多并发请求数量
 */
const requestUserProfile = (uid, max = 2) => {}
|  |      1ChefIsAwesome      2023-05-31 23:02:08 +08:00 via Android 可以再加几种变化: 重试请求。失败的请求插到队列尾重试或者插到下一组重试,重试 n 次之后报错。 按顺序显示结果。比方说并发的 1 、2 个请求,返回顺序是 2 、1 。要求 2 返回时不处理,1 返回时再依次处理 1 、2 。 延迟。并发的一组结束之后,等待一段时间再开始下一组。 | 
|      2gromit1337 OP @ChefIsAwesome 有测试用例的 ```javascript export default async () => { try { const star = Date.now(); const result = await Promise.all([ requestUserProfile("1"), requestUserProfile("2"), requestUserProfile("3"), requestUserProfile("1"), ]); if (Date.now() - star < 2000 || Date.now() - star >= 3000) { throw new Error("Wrong answer"); } if ( !isEqual(result, [ { uid: "1", nick: "nick-1", age: "18", }, { uid: "2", nick: "nick-2", age: "18", }, { uid: "3", nick: "nick-3", age: "18", }, { uid: "1", nick: "nick-1", age: "18", }, ]) ) { throw new Error("Wrong answer"); } return _requestTime === 3; } catch (err) { console.warn("测试运行失败"); console.error(err); return false; } }; ``` | 
|  |      3uncat      2023-06-01 10:24:24 +08:00  1 | 
|  |      4uncat      2023-06-01 10:48:33 +08:00 | 
|  |      5zhy0216      2023-06-02 10:19:47 +08:00 | 
|  |      6zhy0216      2023-06-02 12:08:31 +08:00 ```ts /** * * @param uid uid * @param max 最多并发请求数量 */ const queue: (() => unknown)[] = []; let activeCount = 0; let queueCursor = 0; const requestUserProfile = (uid: string, max = 2) => { return new Promise((resolve) => { const runF = async () => { activeCount++; const r = await requestProfile(uid); activeCount--; if (queueCursor < queue.length) { queue[queueCursor++](); } return resolve(r); }; queue.push(runF); if (activeCount < max) { queue[queueCursor++](); } }); }; ``` |