Skip to content
扫码开始移动端阅读

合并重复请求

537
需要≈
2.685
分钟
手撕面试题
JavaScript

为什么有这个需求?

TIP

比如我有一个获取用户信息的接口,在屎山代码中,可能很多地方都调用了这个接口,恰好,这个优雅的后端连用户信息接口也要返回很久的时候。项目在多个地方使用了这个接口的返回值,这个时候我们就会发现,在页面加载的时候,会出现很多个请求。这样就可以优化成一个请求。

代码

js
import md5 from 'md5';

class TaskQueue {
  constructor() {
    this.taskQueue = new Map(); // 任务队列,用于存储任务ID和任务信息
  }

  // 生成任务ID的函数,使用url、method和data生成MD5哈希
  createTaskId(url, method, data) {
    return md5(`${url}-${method}-${JSON.stringify(data)}`);
  }

  // 核心方法,返回一个Promise
  fetchWithTaskQueue(url, method, data) {
    return new Promise((resolve, reject) => {
      const taskId = this.createTaskId(url, method, data);

      // 检查任务队列中是否已有相同任务
      if (this.taskQueue.has(taskId)) {
        const existingTask = this.taskQueue.get(taskId);
        if (!existingTask.isCompleted) {
          // 如果任务已存在且未完成,观察该任务
          existingTask.promise.then(resolve).catch(reject);
          return;
        }
      }

      // 创建新的任务
      const newTask = {
        isCompleted: false,
        promise: null,
        resolve: null,
        reject: null
      };

      // 创建任务的Promise
      newTask.promise = new Promise((resolveTask, rejectTask) => {
        newTask.resolve = resolveTask;
        newTask.reject = rejectTask;
      });

      // 将新任务加入任务队列
      this.taskQueue.set(taskId, newTask);

      // 发送请求
      fetch(url, {
        method: method,
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
      })
      .then(response => response.json())
      .then(result => {
        // 请求成功时,设置任务完成状态,触发resolve,并删除任务
        newTask.isCompleted = true;
        newTask.resolve(result);
        this.taskQueue.delete(taskId);
        resolve(result);
      })
      .catch(error => {
        // 请求失败时,设置任务完成状态,触发reject,并删除任务
        newTask.isCompleted = true;
        newTask.reject(error);
        this.taskQueue.delete(taskId);
        reject(error);
      });
    });
  }
}

export default TaskQueue;

解析

  • 用md5生成一个唯一的id,然后判断这个任务是否已经存在了,如果存在,则直接观察这个任务,如果不存在,则创建一个新的任务,然后发送请求。
  • 请求成功时,设置任务完成状态,触发resolve,并删除任务。
  • 请求失败时,设置任务完成状态,触发reject,并删除任务。

结尾

我们需要多思考,多总结。才能让我们的代码能更好的服务于我们的业务。

上次更新: