【问题标题】:Await equivalent of 'Promise.resolve().then()'?等待相当于'Promise.resolve().then()'?
【发布时间】:2017-12-18 04:37:12
【问题描述】:

我熟悉 Promises,但继承了一些相当不寻常的代码,而不是创建 new Promise(),而是使用以下代码:

Promise.resolve().then(
  function() {
    // Do useful things
  }
)

根据我的研究,这是一个weird version of setImmediate - 即,在下一次滴答时运行以下函数。

await 的版本是什么?

【问题讨论】:

  • 我相信是(async function(){})(),但我不确定,所以我将其作为评论留下

标签: javascript promise async-await


【解决方案1】:

我继承了一些相当不寻常的代码,而不是使new Promise() 使用Promise.resolve().then(…)。根据我的研究,这是一个奇怪的 setImmediate 版本 - 即,在下一次滴答时运行以下函数。

这是一个副作用,但可能不是此构造的预期目的。要点是then 回调中的“有用代码”是throw-safe 并且可以轻松地return 普通值和类似的承诺,开始一个通常的承诺链。 也可以使用new Promise 编写,但这需要使用resolve 调用而不是通常的return

await 的版本是什么?

字面意思是await Promise.resolve();(可以缩短为等效的await undefined; 语句)。但是,如果仅出于错误处理的目的(很可能)这样做,则忽略它。 async functions 默认会将异常转化为拒绝。

【讨论】:

  • 当我尝试使用 await; 时,typescript 和 eslint 都在 vscode 编辑器中报错:Parsing error: Unexpected token (32:7) eslintExpression expected. ts(1109)。你确定这有效吗?
  • @micnil 啊,不是的。这适用于yield,但不适用于await。感谢您的提醒!
【解决方案2】:

Promise.resolve() 可能有两个不同的原因。您触及了其中之一:

推迟到当前运行的 JS 事件循环结束

这里显而易见的答案是await Promise.resolve();

await undefined 隐含地做同样的事情,但为什么不显式呢?

单一错误处理

Promise.resolve() 也经常出现在用于单一错误处理的 Promise 链的头部:

const doSomething = x => new Promise(r => setTimeout(() => r(x), 1000));

Promise.resolve()
.then(() => doSomething(""())) // bug!
.then(() => doSomething("else"))
.catch(e => console.log("Got " + e)); // Got TypeError: "" is not a function

没有它,第一步可能会抛出异常,这可能是意想不到的!

const doSomething = x => new Promise(r => setTimeout(() => r(x), 1000));

doSomething(""()) // bug!
.then(() => doSomething("else"))
.catch(e => console.log("Got " + e)); // uncaught!

答案是:您不再需要带有 async/await 的 Promise.resolve() 序言。

async 函数隐式捕获同步异常并返回一个被拒绝的 Promise,从而保证单一错误处理和一个 Promise 返回值:

const doSomething = x => new Promise(r => setTimeout(() => r(x), 1000));

(async () => {
  await doSomething(""()); // bug!
  await doSomething("else");
})().catch(e => console.log("Got " + e)); // Got TypeError: "" is not a function

Promise.resolve() kludge 不同,这不仅是一个很好的不变量而且输入更少,它实际上仍然同步调用doSomething

function doSomething() {
  console.log("doSomething() called");
  ""() // bug!
  return new Promise(r => setTimeout(() => r(x), 1000));
}

(async () => {
  await doSomething();
  await doSomething("else");
})().catch(e => console.log("Got " + e)); // Got TypeError: "" is not a function

console.log("here");

这将很难以任何其他方式实现。 async/await 很棒的另一个原因!

【讨论】:

  • “当前运行结束”是否意味着当前刻度的结束?
  • @mikemaccana 是的,JS event loop 的当前运行结束,即currently running task 的结束,或 Node.js 术语中的“滴答”。
  • "await undefined 隐含地做了同样的事情(如await Promise.resolve()" 我只是做了其他观察:await undefined 确实中断同步执行。见jsbin.com/bidonij/edit?js,console
  • @ulrichb await always 中断同步执行,如this fiddle 所示。您的 codepen 显示了其他内容,即在与另一个承诺链比赛时,await Promise.resolve()await undefined 相比,显然排队了一个额外的微任务。很高兴知道。
【解决方案3】:

只是await 的东西。

如果你给await一个不是promise的表达式,它的行为会像

await Promise.resolve(<nonPromiseExpression>)

所以await undefined 将导致异步函数的其余部分异步执行。以setImmediate的这两种实现为例:

var setImmediate = function (fn) {
  Promise.resolve().then(fn);
};

console.log('A');
setImmediate(function () {
  console.log('E');
});
console.log('B');

setImmediate = async function (fn) {
  await undefined;
  fn();
};

console.log('C');
setImmediate(function () {
  console.log('F');
});
console.log('D');

【讨论】:

  • 这个答案可以简化为await undefined;吗?
猜你喜欢
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2014-02-23
  • 2015-02-23
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多