javascript事件循环机制

js是单线程语言

EventLoop包含:一类是基于Browsing Content,一种是基于Worker,二者是独立运行的

console.log('script start')
setTimeout(function(){
	console.log('setTimeout')
},0);
Promise.resolve().then(function(){
}).then(function(){
	console.log('promise')
});
console.log('script end')

整体 script 作为第一个宏任务进入主线程,遇到 console.log,输出 script start
遇到 setTimeout,其回调函数被分发到宏任务 Event Queue 中
遇到 Promise,其 then函数被分到到微任务 Event Queue 中,记为 then1,之后又遇到了 then 函数,将其分到微任务 Event Queue 中,记为 then2
遇到 console.log,输出 script end

结果是 script start, script end, promise1, promise2, setTimeout

任务对列
所有的任务可以分为同步任务和异步任务,正确理解,同步任务一般
会直接进入到主线程中执行,而异步任务,就异步执行的任务,比如ajax网络请求,setTimeout定时器等都属于异步任务,异步任务会通过任务对列(Event Queue)的机制进行协调
在这里插入图片描述
同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入 Event Queue 。主线程内的任务执行完毕为空,会去 Event Queue 读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

在事件循环中,每进行一次循环操作称为tick,通过阅读规范可知,每一次 tick 的任务处理模型是比较复杂的,其关键的步骤可以总结如下:

在此次 tick 中选择最先进入队列的任务( oldest task ),如果有则执行(一次)
检查是否存在 Microtasks ,如果存在则不停地执行,直至清空Microtask Queue
更新 render
主线程重复执行上述步骤

任务分为两大类

task分为两大类,task分为两大类,分别是

宏任务: Macro Task
script(整体代码) setTimeout setInterval I/O
UI 交互事件, setImmediate(Node.js 环境)
微任务: Micro Task
Primose MutaionObserver、process.nextTick(Node.js 环境)
并且每个宏任务结束后,都要清空所有的微任务,这里的Macro Task
setTimeout/Promise 等API便是任务源,而进入任务队列的是由他们指定的具体执行任务。来自不同任务源的任务会进入到不同的任务队列。其中 setTimeout 与 setInterval 是同源的。

console.log('script start');

setTimeout(function() {
  console.log('timeout1');
}, 10);

new Promise(resolve => {
    console.log('promise1');
    resolve();
    setTimeout(() => console.log('timeout2'), 10);
}).then(function() {
    console.log('then1')
})

console.log('script end');

首先,事件循环从宏任务 (macrotask) 队列开始,最初始,宏任务队列中,只有一个 scrip t(整体代码)任务;当遇到任务源 (task source) 时,则会先分发任务到对应的任务队列中去。所以,就和上面例子类似,首先遇到了console.log,输出 script start; 接着往下走,遇到 setTimeout 任务源,将其分发到任务队列中去,记为 timeout1; 接着遇到 promise,new promise 中的代码立即执行,输出 promise1, 然后执行 resolve ,遇到 setTimeout ,将其分发到任务队列中去,记为 timemout2, 将其 then 分发到微任务队列中去,记为 then1; 接着遇到 console.log 代码,直接输出 script end 接着检查微任务队列,发现有个 then1 微任务,执行,输出then1 再检查微任务队列,发现已经清空,则开始检查宏任务队列,执行 timeout1,输出 timeout1; 接着执行 timeout2,输出 timeout2 至此,所有的都队列都已清空,执行完毕。
其输出的顺序依次是:script start, promise1, script end, then1, timeout1, timeout2

最后的最后,记住,JavaScript 是一门单线程语言,异步操作都是放到事件循环队列里面,等待主执行栈来执行的,并没有专门的异步执行线程。。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页