javascript promise同步化的三种方式。

当async方法执行到 await 时,后面的代码就会整体被安排进一个新的微任务,此后的函数体变为异步执行。
MDN async: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await

第一种:Promise队列串行

let list = [];
let taskQueue = []; // 异步任务队列
let isProcessing = false;  // 处理标记,确保队列按顺序处理

async function processTaskQueue() {
  // 如果正在处理队列,直接返回
  if (isProcessing) return;

  isProcessing = true;  // 开始处理队列

  // 只要队列里有任务,就按顺序处理
  while (taskQueue.length > 0) {
    const task = taskQueue.shift(); // 获取并执行队列中的第一个任务
    await task(); // 执行该任务,确保顺序执行
  }

  isProcessing = false; // 队列处理完成
}

async function addToList(item) {
  taskQueue.push(async () => {
    // 异步操作内容
    await new Promise(resolve => setTimeout(resolve, 1000));  // 模拟网络请求

    if (!list.includes(item)) {
      list.push(item);
      console.log(`${item} added.`);
    } else {
      console.log(`${item} already exists.`);
    }
  });

  // 直接调用 processTaskQueue 确保队列开始处理
  await processTaskQueue();
}

// 示例调用
addToList('Item 1');
addToList('Item 2');
addToList('Item 1');  // 这会被判断为重复插入

第二种,防止重复执行,适用于保存、提交类按钮。

来源于:https://innolitics.com/articles/javascript-decorators-for-promise-returning-functions/

let list = [];
let isProcessing = false;

async function addToList(item) {
  // 如果正在处理中,直接返回
  if (isProcessing) return;

  isProcessing = true;  // 锁定,开始处理

  try {
    await new Promise(resolve => setTimeout(resolve, 1000));  // 模拟异步操作

    // 判断是否已存在,避免重复插入
    if (!list.includes(item)) {
      list.push(item);
      console.log(`${item} added.`);
    } else {
      console.log(`${item} already exists.`);
    }
  } finally {
    isProcessing = false;  // 完成后释放锁
  }
}

// 示例调用
addToList('Item 1');
addToList('Item 1');  // 第二个调用会被忽略

第三种:同步装饰器,适用于对单个方法进行队列化执行

const synchronizeDecorator = (decoratee) => {
    const promiseQueue = [];

    const dequeue = () => {
        promiseQueue.splice(0, 1);
    };

    return (...args) => {
        let promise;

        const invokeDecoratee = () => decoratee(...args);

        if (promiseQueue.length === 0) {
            promise = invokeDecoratee();
        } else {
            promise = promiseQueue[promiseQueue.length - 1]
            .then(invokeDecoratee, invokeDecoratee);
        }
        promiseQueue.push(promise.then(dequeue, dequeue));
        return promise;
    };
};

posted @ 2024-12-30 19:22  星小梦  阅读(219)  评论(0)    收藏  举报