【问题标题】:Why do promises and async/await resolve promises in different orders?为什么 promise 和 async/await 以不同的顺序解析 promise?
【发布时间】:2019-09-05 06:06:18
【问题描述】:

从我读过的所有内容来看,async/await 只是 Promise 的语法糖。由此,假设promise_1 和promise_2 都是promise,我希望以下两个函数能够工作:

function promises(promise_1, promise_2) {
    promise_1.then((val) => {
        console.log(val);
        promise_2.then((val2) => {
            console.log(val2);
        });
    });
}
async function asyncawait(promise_1, promise_2) {
    console.log(await promise_1);
    console.log(await promise_2);
}

但是,在测试它们时,我注意到 promises 函数比 async 函数更早地解析了第二个承诺:

let func;
async function test() {
    let promise_1 = Promise.resolve("first");
    let promise_2 = Promise.resolve("second");

    func(promise_1, promise_2);

    console.log("await first");
    await promise_1;
    console.log("awaited first");

    console.log("await second");
    await promise_2
    console.log("awaited second");
}

跑步

func = promises;
test();

产生以下输出:

await first
first
second
awaited first
await second
awaited second

注意在等待 promise_1 之后,promise_1 和 promise_2 是如何解决的。

但是,正在运行

func = asyncawait;
test();

产生以下(预期的)输出:

await first
first 
awaited first
await second
second
awaited second

承诺决议交错。

是什么导致分辨率顺序出现这种差异?

【问题讨论】:

  • 在 chrome 76.0.3809.100 中,这两个函数产生相同的输出。这个测试没有意义,两个承诺在等待之前已经解决,这是一个等待会更快完成的竞争条件。为什么你期望一个 await 解除对另一个的阻塞?
  • 无法复制:jsfiddle.net/bxshwe2t
  • 有趣,这在我的节点测试环境和 Firefox 中都是一致的。猜猜这只是浏览器的怪异。第二种行为是预期的,因为尽管它们都已解决,但一旦 test() 返回,只有第一个 Promise 附加了任何 then() 处理程序。我希望这两个都能在任何新的 then() 创建解析之前解决(例如,有一个 FIFO 队列用于解析)
  • 你使用的是 Babel、TypeScript 还是其他代码转译器?生成的代码不正确是合理的。
  • 是的,使用 TypeScript for Node,但我直接在 Firefox 控制台中得到了这种行为,所以没有转译。

标签: javascript async-await es6-promise


【解决方案1】:

是的,正如您所说的“async/await 只是 Promise 的语法糖”。考虑一下,

function foo(flag){
  return new Promise((res, rej) => {
    setTimeout(() => {
      if(flag) res("Resolved");
      else rej("Rejected")
    },1000);
  })
}

这里的关键是异步函数总是返回一个promise。见return value of a async function

现在,让我们使用这个函数,

function useFoo(){
  return foo(true).then(val => { console.log(val); return val; })
                  .catch(err => { console.log(err); throw err; })
} 

这相当于,

async function useFoo(){
  try{
    const val = await foo(false);
    console.log(val);
    return val;
  }catch(err){
    console.log(err);
    throw err;
  }
}

解释你的行为,

(function(){
  foo(1).then((x)=> console.log(x)); 
  console.log("after foo()");
})()

使用相同的 foo 函数,上面的代码 sn-p 在其他任何内容之前记录 after foo(),因为 foo() 是一个异步函数。对于executor函数的同步操作,是立即执行的,

这就是“async/await 只是 promise 的语法糖”

【讨论】:

  • 抱歉,我不明白这如何解释我的行为。我的测试函数本身被标记为异步,并且打印后的语句就在等待语句之后。
  • @fuzzything44 最后一个 sn-p 解释了你的第一个测试的行为,即 test=promises,
  • 第一个 print 在第一个 promise 的 .then() 中,第二个 print 在第二个 promise 的 .then() 中。您的示例在添加 .then() 处理程序后打印,但在它之外。这并不能解释第一个测试。
猜你喜欢
  • 1970-01-01
  • 2021-04-27
  • 2020-09-03
  • 1970-01-01
  • 2019-11-05
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
  • 1970-01-01
相关资源
最近更新 更多