前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Promise、setTimeout的执行顺序

Promise、setTimeout的执行顺序

作者头像
Snine
发布2022-02-11 08:56:27
6590
发布2022-02-11 08:56:27
举报
文章被收录于专栏:前端开发笔录

Event Loop 这个概念相信大家或多或少都了解过,所谓温故而知新,so,今天,我们就从event loop出发,看看在事件的执行过程中,他都经历了些什么。

什么是event loop

event loop是js的事件执行机制,我们一般简称为事件循环(之所以称作事件循环,是因为它经常被用于类似如下的方式来实现)

代码语言:javascript
复制
while (queue.waitForMessage()){
       queue.processNextMessage();
    }

​ 如果当前没有任何消息queue.waitForMessage 会等待同步消息到达,当完成当前任务后,继续去查看有无需要执行的任务如果需要执行,就再次执行,如此循环,所以称之为事件循环。

同步和异步任务

​ 要了解异步线程我们首先应该明白它的用处,因为js的单线程特性,任务的执行顺序都是依次执行,而当我们在工作中遇到网络请求,前后端交互的时候,你的数据不会马上拿到,这需要时间,如果等拿到数据再执行下面的代码,这样如果多次请求就会发现加载速度极慢,这样显然不合理,这样就会出现很多次的暂停等待,所以这时候 需要执行异步任务,当我们发起请求时候,采用异步的方式,浏览器检测到其为异步时,就会开辟一个新的进程处理该函数,然后继续执行后面的任务,当完成了执行栈里的同步任务之后,再检测是否有异步任务需要执行,最后执行异步任务。

代码语言:javascript
复制
-同步任务进入主线程,按顺序从上而下依次执行,
-异步任务,进入`event table` ,注册回调函数 `callback` ,
 任务完成后,将`callback`移入`event queue`中等待主线程调用
异步任务分为微任务和宏任务

​ 在执行过程中,我们知道了同步任务会优先异步任务执行,那么在异步中呢,异步中同样包含微任务和宏任务,首先我们大概了解下微任务和宏任务,在js中:

  • 微任务(micor Task) :promise MutationObserver process.nextTick
  • 宏任务(macro Task):script settimeout setinterval setImmediate requestAnimationFrame

宏任务 #浏览器nodeI/O√√setTimeOut√√setInterval√√setImmediate×√requestAnimationFrame√×

微任务 #浏览器nodeprocess.nextTick×√MutationObserver√×Promise.then catch finally√√

这两种任务在不同环境下支持的各不同,今天我们主要看看在浏览器中,我们经常会遇到的有 promisesetTimeout 我们通过下面这段代���来看看:

代码语言:javascript
复制
console.log(1)

setTimeout(() => console.log(2), 0)

new Promise((resolve, reject) => {
    console.log(3)
    resolve()
}).then(() => {
    console.log(4)
})

首先来分析下,这段代码中包含同步任务,包含异步的宏任务setTimeout,包含异步的微任务promise,这套题的答案是1.3.4.2 ,我们首先找到同步任务,1 3 是同步任务,然后执行异步任务,异步任务如果按顺序执行则是24 但是答案是4.2那么我们可以知道 promise的执行顺序优先于setTimeout所以由此可知,在异步任务中,微任务优先于宏任务执行,可以看看下图。

eventloop
eventloop

红线就是任务的执行顺序

黑线是任务的结构

看完这么多下面来完成下面这道题并加以分析:

代码语言:javascript
复制
console.log(1)
setTimeout(() => {
    console.log(2)
    new Promise((resolve, reject) => {
        console.log(3)
        resolve()
    }).then(() => {
        console.log(4)
    })
}, 0)
new Promise((resolve, reject) => {
    console.log(5)
    resolve()
}).then(() => {
    console.log(6)
})
setTimeout(() => {
    console.log(7)
    new Promise((resolve, reject) => {
        console.log(8)
        resolve()
    }).then(() => {
        console.log(9)
    })
}, 0)
console.log(10)
const promise = new Promise((resolve, reject) => {
    console.log(1);
    console.log(2);
  });
  promise.then(() => {
    console.log(3);
  });
  console.log(4);

答案:1 , 5 , 10 , 6 , 2 , 3 , 4 , 7 , 8 , 9

​ 废话不多说直接解题

  • 进入主线程开始执行, 遇到 console.log(1), 输出 1
  • 遇到一个 setTimeout 宏任务, 将其回调函数推入 macro Taskevent queue 中,macro Taskevent queue 中记一个任务 setTimeout1
  • 然后碰到 promise 微任务, 直接执行 new Promise 输出 5, 并将 then 函数的回调函数推入 micro Taskevent queue 中, micro Taskevent queue 中记 一个 微任务 promise1
  • 又遇到了 setTimeout 宏任务, 同理,将其回调函数推入 macro Taskevent queue 中,macro Taskevent queue 中记一个任务 setTimeout2
  • 最后,执行 console.log(10), 输出 10

上一轮事件循环结束,我们发现,已经输出 1 5 10 了, 按照我们之前所说,这个时候,主线程会去检查 是否存在微任务,不难发现,这个时候的 event queue 是这个样子的

micro Task (微任务)

macro Task(宏任务)

promise1

setTimeout1

setTimeout2

代码语言:javascript
复制
主线程 ---> promis1 ---> settimeout1 ---> settimeou2 ---> 循环检查主线程任务栈是否还有任务
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是event loop
  • 同步和异步任务
  • 异步任务分为微任务和宏任务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档