美文网首页
事件循环机制

事件循环机制

作者: 泪滴在琴上 | 来源:发表于2018-12-02 15:17 被阅读9次

同步任务和异步任务

同步任务 即可以立即执行的任务,例如 console.log() 打印一条日志、声明一个变量或者执行一次加法操作等。
异步任务 相反不会立即执行的事件任务。异步任务包括宏任务和微任务。

常见的异步操作:

Ajax
DOM的事件操作
setTimeout
Promise的then方法
Node的读取文件

宏任务(macrotask)

script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering

微任务(macrotask)

process.nextTick, Promise.then(), Object.observe, MutationObserver

在微任务中 process.nextTick 优先级高于Promise

当一个异步任务入栈时,主线程判断该任务为异步任务,并把该任务交给异步处理模块处理,当异步处理模块处理完打到触发条件时,根据任务的类型,将回调函数压入任务队列。
如果是宏任务,则新增一个宏任务队列,任务队列中的宏任务可以有多个来源。
如果是微任务,则直接压入微任务队列

执行机制:

1、从全局任务 script开始,任务依次进入栈中,被主线程执行,执行完后出栈。
2、遇到异步任务,交给异步处理模块处理,对应的异步处理线程处理异步任务需要的操作,例如定时器的计数和异步请求监听状态的变更。
3、当异步任务达到可执行状态时,事件触发线程将回调函数加入任务队列,等待栈为空时,依次进入栈中执行。

到这问题就来了,当异步任务进入栈执行时,是宏任务还是微任务呢?
1、由于执行代码入口都是全局任务 script,而全局任务属于宏任务,所以当栈为空,同步任务任务执行完毕时,会先执行微任务队列里的任务。
2、微任务队列里的任务全部执行完毕后,会读取宏任务队列中拍最前的任务。
3、执行宏任务的过程中,遇到微任务,依次加入微任务队列。
4、栈空后,再次读取微任务队列里的任务,依次类推。

总之:先是同步任务,完了微任务,再是宏任务,当宏任务包含微任务,先执行微任务,再继续宏任务

看下面的实例:

setTimeout(function () {
   console.log(1);
   Promise.resolve().then(function () {
       console.log(2);
   });
}, 0);
setTimeout(function () {
   console.log(3);
}, 0);
Promise.resolve().then(function () {
   console.log(4);
});
console.log(5);

第一轮循环

1、同样从全局任务入口,遇到宏任务 setTimeout,交给异步处理模块,我们暂且先记为 setTimeout1,由于等待时间为 0,直接加入宏任务队列。
2、再次遇到宏任务 setTimeout,交给异步处理模块,我们暂且先记为 setTimeout2,同样直接加入宏任务队列。
遇到微任务 then(),加入微任务队列。
3、最后遇到打印语句,直接打印日志 5。


image.png

第二轮循环

1、栈空后,先执行微任务队列中的 then()方法,输出 4,此时微任务队列为空。


image.png

第三轮循环

1、先执行微任务队列中的 then()方法,输出 2,此时微任务队列为空。


image.png

2、继续读取宏任务队列的最靠前的任务 setTimeout2。
3、直接执行打印语句,打印日志 3。第三轮循环结束,执行完毕。


image.png

最后我们是我们的boss,欢迎大家在评论区留言写出自己心中的那个正确答案。

console.log('1');
setTimeout(function() {
   console.log('2');
   new Promise(function(resolve) {
       console.log('3');
       resolve();
   }).then(function() {
       console.log('4')
   })
})
new Promise(function(resolve) {
       console.log('5');
       resolve();
}).then(function() {
       console.log('6')
})
setTimeout(function() {
   console.log('7');
})
setTimeout(function() {
   console.log('8');
   new Promise(function(resolve) {
       console.log('9');
       resolve();
   }).then(function() {
       console.log('10')
   })
})
new Promise(function(resolve) {
   console.log('11');
   resolve();
}).then(function() {
   console.log('12')
})
console.log('13');
14794476814794920.png

相关文章

  • 并发:事件循环 & asyncio

    1. 事件循环机制 1.1. 什么是事件循环 事件循环(Event Loop),即通过轮询方法监控事件; asyn...

  • 《浏览器工作原理与实践》学习笔记(四)

    消息队列和事件循环 要想在线程运行过程中,能接收并执行新的任务,就需要采用事件循环机制。 事件循环机制:相比于线性...

  • 事件循环机制

    同步任务和异步任务 同步任务 即可以立即执行的任务,例如 console.log() 打印一条日志、声明一个变量或...

  • 事件循环机制

    js是单线程的。浏览器: js执行线程:负责执行js代码 UI线程:负责UI展示,负责展示给用户看到的页面 js事...

  • 事件循环机制

    事件循环(evenloop) 事件循环机制是宿主环境提供的。js中处理异步,增加了任务队列的概念(你不知道的js中...

  • 事件循环机制

    静下心学了一波事件循环机制,好开心,我学会了,首先还是得感谢作者写的笔记特别详细 链接: http://www.c...

  • 事件循环机制

    Javascript是单线程执行的,出现异步时,并不会阻塞JS的执行,而是接着往下执行,等到异步结果返回时再处理。...

  • 事件循环机制

    JS 有个全局的函数执行栈,这是执行同步函数的地方 除了函数执行栈,还有一个事件队列,这是执行异步函数的地方 异步...

  • 事件循环机制

    想要了解javascript的事件循环机制,首先从基础概念出发;关于线程和进程 进程好比图中的工厂;有单独的的自己...

  • 事件循环机制

    JS中存在一个叫做执行栈的东西。JS的所有同步代码都在这里执行,当执行一个函数调用时,会创建一个新的执行环境并压到...

网友评论

      本文标题:事件循环机制

      本文链接:https://www.haomeiwen.com/subject/rjvjcqtx.html