在 Promise/Async/Await 中订购(采访问题)
Order in Promise/Async/Await (Interview Question)
问题:
new Promise((resolve) => {
console.log(1)
resolve()
}).then(async () => {
console.log(2)
}).then(async () => {
console.log(3)
})
new Promise((resolve) => {
console.log('a')
resolve()
}).then(() => {
console.log('b')
}).then(() => {
console.log('c')
}).then(() => {
console.log('d')
}).then(() => {
console.log('e')
})
答案:
1
一种
2个
b
C
d
3个
e
但我认为答案是.... 1 a 2 b 3 c d e
请帮助分享如何思考以获得详细的答案。谢谢
首先我要解释一下,任何人都不应该依赖两个独立的承诺链之间的精确时间。它们 运行 相互独立,一旦你在其中任何一个承诺链中插入 任何现实世界的异步操作 (所有 real-world 编程都包含), 那么每个链的时间相对于另一个是完全不可预测的。
相反,实际代码中的时间取决于异步操作的时间,而不是其他任何东西。想象一下,这个承诺链中的每个步骤都在读取文件或做一些随机延迟。这些是完全不可预测的操作,因此哪个链先做什么取决于实际异步操作的时间,而不是本例中显示的内容。
因此,试图详细分析每个项目何时进入承诺作业队列以及何时获得服务完全是在浪费编程时间,对任何实际编程问题都没有用。
此外,如果您确实需要特定的操作顺序,则不要使用两个独立的承诺链进行编程。相反,您使用 promise flow-of-control 工具(例如将所有内容链接到一个链中或使用 Promise.all()
、Promise.race()
等...)来引导 execution/completion 订单完全符合您的要求希望它不考虑 promise 实现的详细内部工作原理。
然后,我将通过遍历其中一个承诺链的前两个链接来解释承诺队列如何工作的基础知识,只是为了表明我了解承诺如何被解析、添加到承诺队列以及然后,当控制即将 return 到事件循环时,承诺队列中最旧的项目到达 运行 并调用其 .then()
或 .catch()
处理程序。这只是为了说明您了解如何安排 promise 的基础知识,以及它们从它们自己的作业队列中以 LIFO 顺序获得服务,并且在事件循环中的大多数其他事情之前。
然后,我要解释一下,几年前,为了提高性能而对一些承诺步骤进行了更改,而在该规范更改之前或之后的 JS 引擎可能会为当时的情况产生不同的结果。您不应该依赖该级别的实施细节的另一个原因。
如果面试官坚持让我尝试解释这个问题的精确顺序并且不听我的推理为什么这是一个毫无意义的练习,即使在听了我如何编写真实世界情况的代码之后执行顺序确实很重要,除非这只是一些真正的初级面试官试图变得聪明(并且超越自己),否则我不得不得出结论,这不是一个好的工作场所。任何高级开发人员都不应坚持认为这是一个非常有价值或实用的练习,除了表明您对 promise 作业队列的工作原理有基本的了解。
问题:
new Promise((resolve) => {
console.log(1)
resolve()
}).then(async () => {
console.log(2)
}).then(async () => {
console.log(3)
})
new Promise((resolve) => {
console.log('a')
resolve()
}).then(() => {
console.log('b')
}).then(() => {
console.log('c')
}).then(() => {
console.log('d')
}).then(() => {
console.log('e')
})
答案:
1 一种 2个 b C d 3个 e
但我认为答案是.... 1 a 2 b 3 c d e
请帮助分享如何思考以获得详细的答案。谢谢
首先我要解释一下,任何人都不应该依赖两个独立的承诺链之间的精确时间。它们 运行 相互独立,一旦你在其中任何一个承诺链中插入 任何现实世界的异步操作 (所有 real-world 编程都包含), 那么每个链的时间相对于另一个是完全不可预测的。
相反,实际代码中的时间取决于异步操作的时间,而不是其他任何东西。想象一下,这个承诺链中的每个步骤都在读取文件或做一些随机延迟。这些是完全不可预测的操作,因此哪个链先做什么取决于实际异步操作的时间,而不是本例中显示的内容。
因此,试图详细分析每个项目何时进入承诺作业队列以及何时获得服务完全是在浪费编程时间,对任何实际编程问题都没有用。
此外,如果您确实需要特定的操作顺序,则不要使用两个独立的承诺链进行编程。相反,您使用 promise flow-of-control 工具(例如将所有内容链接到一个链中或使用 Promise.all()
、Promise.race()
等...)来引导 execution/completion 订单完全符合您的要求希望它不考虑 promise 实现的详细内部工作原理。
然后,我将通过遍历其中一个承诺链的前两个链接来解释承诺队列如何工作的基础知识,只是为了表明我了解承诺如何被解析、添加到承诺队列以及然后,当控制即将 return 到事件循环时,承诺队列中最旧的项目到达 运行 并调用其 .then()
或 .catch()
处理程序。这只是为了说明您了解如何安排 promise 的基础知识,以及它们从它们自己的作业队列中以 LIFO 顺序获得服务,并且在事件循环中的大多数其他事情之前。
然后,我要解释一下,几年前,为了提高性能而对一些承诺步骤进行了更改,而在该规范更改之前或之后的 JS 引擎可能会为当时的情况产生不同的结果。您不应该依赖该级别的实施细节的另一个原因。
如果面试官坚持让我尝试解释这个问题的精确顺序并且不听我的推理为什么这是一个毫无意义的练习,即使在听了我如何编写真实世界情况的代码之后执行顺序确实很重要,除非这只是一些真正的初级面试官试图变得聪明(并且超越自己),否则我不得不得出结论,这不是一个好的工作场所。任何高级开发人员都不应坚持认为这是一个非常有价值或实用的练习,除了表明您对 promise 作业队列的工作原理有基本的了解。