ITADN
tc39/proposal-promise-with-resolvers
tc39/proposal-promise-with-resolvers · 文件 下载 ZIP
文件最后提交记录最后更新时间
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

Promise.withResolvers

注意:该提案现已处于 阶段 4。规格 PR 见此处:https://github.com/tc39/ecma262/pull/3179

状态

阶段:4

支持者:

作者:

阶段 3 幻灯片 阶段 2 幻灯片 阶段 1 幻灯片

概要

当手动实现 Promise 时,用户必须传入一个执行器回调,该回调接收两个参数:一个 resolve 函数,用于触发 Promise 的解决;以及一个 reject 函数,用于触发 Promise 的拒绝。如果回调能够嵌入对异步函数的调用,且该调用最终会触发解决或拒绝,例如注册事件监听器,那么这种方式效果良好。

const promise = new Promise((resolve, reject) => {
  asyncRequest(config, response => {
    const buffer = [];
    response.on('data', data => buffer.push(data));
    response.on('end', () => resolve(buffer));
    response.on('error', reason => reject(reason));
  });
});

然而,开发者通常希望在实例化 Promise 之后配置其 resolve 和 reject 行为。目前,这需要一种繁琐的变通方法,从回调作用域中提取 resolve 和 reject 函数:

let resolve, reject;
const promise = new Promise((res, rej) => {
  resolve = res;
  reject = rej;
});
asyncRequest(config, response => {
  const buffer = [];
  response.on('callback-request', id => {
    promise.then(data => callback(id, data));
  });
  response.on('data', data => buffer.push(data));
  response.on('end', () => resolve(buffer));
  response.on('error', reason => reject(reason));
});

开发者可能还有需要向多个调用者传递 resolve/reject 的要求,因此他们必须以这种方式实现:

let resolve = () => { };
let reject = () => { };

function request(type, message) {
  if (socket) {
    const promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });
    socket.emit(type, message);
    return promise;
  }

  return Promise.reject(new Error('Socket unavailable'));
}

socket.on('response', response => {
  if (response.status === 200) {
    resolve(response);
  }
  else {
    reject(new Error(response));
  }
});

socket.on('error', err => {
  reject(err);
});

这是开发者经常反复编写的样板代码。本提案仅旨在为 Promise 构造函数添加一个静态方法,暂定名为 withResolvers,该方法返回一个 promise,并方便地暴露其 resolution 和 rejection 函数。

const { promise, resolve, reject } = Promise.withResolvers();

这种方法或类似的方法可能已被某些委员会成员以 deferdeferred 的名称所知晓,这些名称有时也用于生态系统中的实用函数。该提案采用更具描述性的名称,以方便可能不熟悉这些历史函数的用户。

现有实现

库和应用不断重新发明这个轮子。以下仅列举少数示例。

示例
React内联示例
Vue内联示例
Axios内联示例
TypeScript实用函数
Vite内联示例
Deno stdlib实用函数