javascript 请求队列

150 阅读1分钟

一、前言

业务中遇到一个需求,所有修改操作都需要同步完成,即完成上一个请求之后才能发送下一个请求,当时没有找到好的方案,暂时用以下方式封装请求方法。哪位大佬有更好的实现方式可以放在评论区哦😯

二、实现

export interface IResponseData {
  code: number;
  zpData: any;
  message: string;
}
type IJob = {
  getParams: (...args: any[]) => any;
  fn: (...args: any[]) => Promise<any>;
  cb?: (...args: any[]) => void;
  // 如果你的参数和执行时的状态无关,则可以用 params ,否则请用getParams(如,参数中包含请求时的时间or version等动态的参数时)
  params?: any;
};

// 资源
const requestQueue: IJob[] = [];
let dealMachine = "idle";
const resolveQueue: any[] = [];
const rejectQueue: any[] = [];


export function queueRequest(job: IJob): Promise<IResponseData> {
  requestQueue.push(job);


  // 如果处理机空闲,继续执行下一个任务
  if (dealMachine == "idle") {
    requestPop();
  }
  return new Promise((resolve, reject) => {
    resolveQueue.push(resolve);
    rejectQueue.push(reject);
  });
}

function requestPop() {
  const job = requestQueue.shift();
  if (job) {
    // 如果有job,处理机处于 busy 状态
    dealMachine = "busy";
    job
      .fn(job.params || job.getParams())
      .then(res => {
        job.cb && job.cb(res);
        const resolve = resolveQueue.shift();
        if (resolve) {
          resolve(res);
        }
      })
      .catch(error => {
        const reject = rejectQueue.shift();
        if (reject) {
          reject(error);
        }
      })
      .finally(() => {
        // 执行完成,处理机处于 idle 状态
        dealMachine = "idle";
        requestPop();
      });
  }
}

三、例子

functin savePosition() {
    const res = await queueRequest({
        fn: _saveItemPosition,
        getParams: () => ({
          paletteId: route.params.paletteId, // 画板id
          itemPositionList,
          version: versionManager.version, // 版本号
        }),
      });
      if (res.code == 0) {

      } else {

      }
}