为什么 Promise 比setTimeout() 快?

解析

  Promise.resolve(1).then(function resolve(){
   console.log("resolved")
 })
setTimeout(function timeout(){
  console.log("timeout")
},0)

// resolved
// timeout
promise.reslove(1)是一个静态函数,它返回一个立即解析的promise。setTimeout(call把车开,0)是以0毫秒的延迟回调函数。
打印结果 先resolved 后timeout,因此立即解决的promise比setTimeout更快
是因为promise.resolve(true).then(…)在setTimeout之前已经被调用了,所以promise会更快

js执行机制是自上而下执行

   setTimeout(function timeout(){
  console.log("timeout")
},0)
  Promise.resolve(1).then(function resolve(){
   console.log("resolved")
 })
 
// resolved
// timeout

二者互换位置后,打印的结果还是不变

事件循环

与异步js相关的问题可以通过研究事件循环,回顾一下js的工作方式主要组成部分

在这里插入图片描述

调用堆栈 是一个LIFO(后进先出)结构。它存储在代码执行期间创建的执行的上下文,简单的说,调用堆栈执行这些函数
  • web api 是异步操作(fetch请求,promise,计时器)及其回调待完成的地方
  • task queue(任务队列)是一个FIFO(先进先出)结构,他保存准备执行的异步操作的回调函数,例如:超时的setTimeout()的回调函数或准备执行的单击按钮事件处理程序都在任务队列中排队
  • job queue(作业队列)是一个FIFO(先入先出)结构,他保存准备执行的Promise的回调,例如:已经完成的resolve和reject回调被排在作业队列中
  • 最后,事件循环永久监听调用堆栈是否为空,如果调用堆栈为空 ,则事件循环查看作业队列或者任务队列,并准备执行的任何回调分派到调用堆栈中

作业队列与任务队列

我们从事件循环的角度来看,对代码执行进行一步步的分析
  • 调用堆栈执行setTimeout(callbask,0)并计划一个计时器,timeout回调存储在web api 中
 setTimeout(function timeout(){
 console.log("timeout)
},0)
Promise.reslove(1).then(function resolve(){
console.log('resolved')
})

在这里插入图片描述

  • 调用堆栈执行Promise.resolve(true).then(resolve)并安排一个promise解决方案。resolved()回调存储在web api 中
    在这里插入图片描述
  • promise立即被解析,同事定时器也立即执行,这样定时器timeout进入任务队列,promise回调进入作业队列
    在这里插入图片描述
  • 现在有趣的部分,作业队列(微任务)优先级高于任务队列(宏任务)。事件循环从作业队列中取出promise回调resolve()并将其放入调用堆栈中,然后,调用堆栈执行promise回调resolve
    在这里插入图片描述
  • 最后,事件循环将计时器回调timeout从任务队列中到调用堆栈中,然后将用堆栈执行计时器回调timeout
    在这里插入图片描述
调用堆栈为空,完成脚本执行
为什么立即解决的 promise 比立即执行定时器处理得更快?

由于事件循环优先级的存在,因此与任务队列(存储超时的setTimeout()回调)相比,作业队列(用于存储已实现的Promise回调)的优先级更高。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值