Promise vs setTimeout

fra*_*ies 32 javascript asynchronous

我在以下代码中观察到:

setTimeout(function(){console.log('setTimeout')});
Promise.resolve(1).then(function(){console.log('promise resolve')})
Run Code Online (Sandbox Code Playgroud)

无论我执行多少次,promise回调总是在setTimeout之前记录.

我的理解是两个回调都安排在下一个时钟执行,而我真的不明白发生了什么使得承诺总是优先于超时.

Moh*_*ara 28

Promise.resolve计划一个微任务,setTimeout计划一个macrotask.并且在运行下一个macrotask之前执行微任务.

  • 那是最接近的答案.我会添加链接到任务/微任务的深层解释.https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ (6认同)
  • 另外值得一提的是,微任务的来源可能只有两件事:MutationObserver 和 Promises。 (2认同)

Myk*_*yuk 22

简短回答Promise比事件循环堆栈中的setTimeout回调函数(或我如何理解它)具有更好的优先级.

很长的回答观看此视频.很有帮助.希望这可以帮助.

https://www.youtube.com/watch?v=8aGhZQkoFbQ

感谢@MickJuice为事件循环提供新的和更新的视频.

https://www.youtube.com/watch?v=cCOL7MC4Pl0

  • 这是一个很棒的视频.这个是帮助您了解任务和事件的优先事项:https://www.youtube.com/watch?v = cCOL7MC4Pl0 (6认同)
  • 在另一个答案的评论中提到的一篇好文章:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ (2认同)

nnn*_*nnn 14

setTimeout()拥有4ms的最小延迟,所以即使你没有指定代码中的延迟超时仍将至少4毫秒延迟..then()在此期间你的承诺被召唤.

  • 即使没有4ms的限制优化,无论如何,承诺会更快.因为`setTimeout`创建任务而'Promise`创建微任务(作业).这是真正的原因. (3认同)

Jua*_*dez 8

超时Promise都用于以异步方式执行代码,但具有不同的特征和目的:

\n\n

setTimeout \n- 将函数的执行延迟特定的持续时间。\n- 不阻止其余代码执行(异步行为)\n- 它们创建 Macrotask(浏览器内部操作)

\n\n

Promises \n- 它们是允许异步执行代码的包装器(例如:ajax 调用)。(不依赖于特定的持续时间)\n- 它们对于链接不同的异步调用特别有用。\n- 不会阻止其余的代码执行(异步行为),除非您使用等待运算符。\n-他们创建Microtask(浏览器内部操作),其优先级高于Macrotask

\n\n

推荐

\n\n
    \n
  • 当您想要延迟函数执行一段特定的时间而不阻止进程中其余代码的执行时,请使用setTimeout

  • \n
  • 使用承诺 :\n当你想要执行一些异步代码并避免 \xe2\x80\x9ccallback 地狱\xe2\x80\x9d (是的,因为你可以在没有 Promises 的情况下进行异步 ajax 调用,但语法不太清晰,更容易出现错误)

  • \n
\n


Jon*_*lms 5

这与Web Spec中定义的事件循环有关。浏览器有多个任务队列用于多种类型的任务(例如通过创建的定时器任务),以及一个微任务队列(Promise 结算被推送到的地方)。每当浏览器完成执行任务时,它都会清空微任务队列并执行其中的所有任务,然后再继续执行另一个任务队列中的任务。setTimeout

\n\n

因此,代码执行后(即任务),Promise结算在微任务队列中,而定时器任务可能已经在任务队列\xc2\xb9中。微任务队列被清空并且 Promise 被解析。然后,当计时器任务运行时。

\n\n

\xc2\xb9 浏览器可能会选择稍微增加超时,而且他们确实这样做了。在大多数浏览器中,超时将永远不会在 0 毫秒后运行。

\n