You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现无返回值异步方法的链式顺序执行?

实现无感知链式调用的顺序异步API

这需求太常见了!要让用户不用管Promise,直接链式调用异步方法还能保证顺序,核心就是在API类内部维护一个Promise任务队列,让每个方法都等前一个异步操作完成后再执行,同时每次调用都返回实例本身,保持链式的连贯性。

完整实现代码

class Api {
  constructor() {
    // 初始化一个已完成的Promise作为队列起点,确保第一个任务能直接执行
    this.promiseQueue = Promise.resolve();
  }

  // 内部工具方法:把异步任务加入队列
  #enqueue(task) {
    // 把新任务串到队列末尾,更新队列的Promise引用
    this.promiseQueue = this.promiseQueue
      .then(() => task())
      .catch(err => {
        // 可选:捕获错误避免队列中断,这里做个日志输出
        console.error('异步任务执行出错:', err);
      });
    // 返回实例本身,支持链式调用
    return this;
  }

  // 公开的异步方法1
  doAsync() {
    return this.#enqueue(() => {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('doAsync 执行完毕');
          resolve();
        }, 1000);
      });
    });
  }

  // 公开的异步方法2
  doAnotherAsync() {
    return this.#enqueue(() => {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('doAnotherAsync 执行完毕');
          resolve();
        }, 800);
      });
    });
  }

  // 公开的异步方法3
  doAThirdAsync() {
    return this.#enqueue(() => {
      return new Promise(resolve => {
        setTimeout(() => {
          console.log('doAThirdAsync 执行完毕');
          resolve();
        }, 500);
      });
    });
  }

  // 可选:给用户提供等待所有任务完成的方法
  wait() {
    return this.promiseQueue;
  }
}

怎么用?完全符合你的需求!

const api = new Api();
// 直接链式调用,不用加await或者.then
api.doAsync().doAnotherAsync().doAThirdAsync();

// 要是偶尔需要等所有任务都做完,还能用wait方法
api.doAsync().doAnotherAsync().wait().then(() => {
  console.log('所有异步任务都执行完啦!');
});

执行后控制台的输出顺序会严格按照调用顺序来:

doAsync 执行完毕(1秒后)
doAnotherAsync 执行完毕(再过0.8秒)
doAThirdAsync 执行完毕(再过0.5秒)

关键逻辑拆解

  • 队列初始化:构造函数里用Promise.resolve()创建一个已完成的Promise,作为队列的“起点”,这样第一个异步任务不需要等待就能直接执行。
  • 任务入队:#enqueue是核心私有方法,它接收一个返回Promise的任务函数,把这个任务通过.then()串到队列的末尾,同时更新队列的Promise引用。这样每个新任务都会自动等待前一个任务完成。
  • 链式调用支持:每个公开方法调用#enqueue后都会返回this(也就是API实例),所以用户可以一直链式写下去,完全不用关心Promise的存在。
  • 错误处理:加了catch块捕获单个任务的错误,避免某个任务失败导致整个队列中断。如果需要失败后终止队列,直接去掉catch或者在catch里重新抛出错误就行。

内容的提问来源于stack exchange,提问作者richbai90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:33:21