为什么setTimeout在promise后执行

  • 首先要知道,在 ES3 和更早的版本中,JavaScript 本身还没有异步执行代码的能力,只能由浏览器或宿主环境传递给JavaScript引擎一段任务,然后将其顺序执行。这就是宿主环境发起的任务。我们称其为宏观任务。
  • 在ES5之后,JavaScript引进了promise,使得JavaScript引擎可以自己发起执行任务,我们称其为微观任务。
  • 每次执行任务时我们可以理解为一个宏观任务,每次都是执行完一个宏观任务再执行下一个宏观任务,而promise在执行时会返回一个异步任务,这时候怎么办呢,JavaScript引擎要保证这些异步任务要在同一个宏观任务中执行,因此就出现了微观任务队列。
  • 有了这个机制,在执行任务时,JavaScript将promise产生的异步任务加入到宏观任务尾部的微观任务队列中,而setTimeout是由宿主发起的任务,自然就是一个宏观任务,因此排在了前一个宏观任务的后面执行。
  • 也就是说,正常情况下,promise.then中执行的任务一定会在setTimeout之前执行。
### JavaScript 中 `setTimeout` 和 `Promise` 的执行顺序及其背后的原理 在 JavaScript 的事件循环机制中,任务被分为两类:宏任务(Macro Task)和微任务(Micro Task)。两者的区别在于它们的执行时机不同。 #### 宏任务与微任务的概念 - **宏任务** 是指那些会在当前任务完成后进入事件队列的任务,常见的有 `setTimeout`, `setInterval`, UI 渲染等。 - **微任务** 则是指那些优先于下一个宏任务之前被执行的任务,典型的例子包括 `Promise.then/catch/finally`, `MutationObserver` 等。 当一段代码中有多个宏任务和微任务时,其执行顺序遵循以下原则: 1. 当前同步代码块中的所有操作会立即完成。 2. 随后依次处理所有的微任务队列中的任务,直到清空为止。 3. 接着才会继续处理宏任务队列中的下一项任务[^1]。 #### 示例分析 考虑下面这段代码: ```javascript console.log('Start'); setTimeout(() => { console.log('Timeout'); }, 0); new Promise((resolve) => { resolve(); }).then(() => { console.log('Promise resolved'); }); console.log('End'); ``` 在这段代码中,“Start” 和 “End” 属于主线程上的同步代码部分,因此会最先打印出来。接着,由于 `Promise` 的 `.then()` 方法注册了一个微任务,它会被加入到微任务队列;而 `setTimeout` 注册的是一个宏任务,所以它的回调函数会被放入宏任务队列。按照上述规则,在同步代码结束后,JavaScript 引擎会先检查并运行微任务队列中的所有任务,然后再回到宏任务队列去取新的任务来执行。最终输出结果将是: ``` Start End Promise resolved Timeout ``` 此行为说明了即使设置了延迟时间为零秒 (`0ms`) 的 `setTimeout` 调用,只要存在未解决的微任务,它仍然不会立刻得到执行[^3]。 #### 更深层次探讨——异步编程模式下的扩展应用 对于更复杂的场景比如涉及 `async/await` 关键字的情况,则可以进一步理解为这些关键字本质上也是基于 Promises 实现的一种语法糖形式。例如定义如下函数: ```javascript async function asyncFunction() { await new Promise(resolve => setTimeout(resolve, 100)); console.log("Async Function"); } asyncFunction(); console.log("Main Thread"); ``` 这里虽然看起来像是阻塞了一段时间再继续向下走流程但实际上并非如此。“Await”的作用仅限于暂停所在上下文中后续语句直至指定条件满足即内部隐含创建出来的那个 promise 对象状态变为 fulfilled 后才恢复控制流向前推进而不是真的让整个程序停下来等待一段时间过去后再回来做别的事情[^2]. #### 总结 综上所述,无论是简单还是复杂的应用场合里头都离不开对这两种不同类型工作单元之间相互关系的认识掌握才能写出更加高效稳定可靠的前端应用程序代码.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值