【问题标题】:How does this setTimeout get called before Promise?这个 setTimeout 如何在 Promise 之前被调用?
【发布时间】:2020-05-07 22:16:43
【问题描述】:

所以过去一天我一直在研究事件循环和微/宏任务队列。我已经看到很多人对以下代码的直接矛盾:

setTimeout(() => console.log("A"), 0);

const futureData = fetch('someUrl') // assume this takes 300ms
futureData.then(x => console.log("B"))

console.log("C")

// output -> C, A, B
// what multiple JS instructors says the output will be -> C, B, A

我得到的实际输出写在上面。但是,在我正在学习的课程中,讲师认为由于futureData 是一个 Promise,它会被推送到微任务队列中,并且由于它会被推送到微任务队列中,因此它将在任何操作之前先执行宏任务,例如 setTimeout。

但是运行它之后,这真的是公然错误的吗?我在这里缺少什么吗?为什么合格的教练会这么说,我几乎可以肯定我错过了一条重要的信息。

我的想法是,只有已解决的 Promise 会被推送到微任务队列,而所有待处理的 Promise 都必须等到未来的事件循环轮次。

我错过了什么?

【问题讨论】:

  • setTimeout()fetch() 不是一个公平的测试。如果fetch() 赢得比赛,那将是相当惊人的。尝试用racingsetTimeout() 代替Promise.resolve("B")
  • @Roamer-1888 是的,在这种情况下,Promise.resolve("B") 总是赢。我认为这基本上归结为微任务是否有足够的时间在所有同步操作运行之前排队。
  • 我会说它归结为fetch() 是一个冗长的操作。

标签: javascript node.js promise


【解决方案1】:

我认为只有在 WebApis 或其他线程处理了异步部分并且只有回调被推送到队列之后才能将异步任务推送到微/宏任务,这些回调将在主线程本身上运行。

由于fetch 正在占用300ms,因此当堆栈为空时,MicroTask 队列中还没有承诺回调,但宏中存在 SetTimeout。

【讨论】:

    猜你喜欢
    • 2021-09-17
    • 2016-05-13
    • 1970-01-01
    • 2018-05-28
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多