事件循环和任务队列
Posted zhanghaiyu-jade
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了事件循环和任务队列相关的知识,希望对你有一定的参考价值。
如有错误欢迎指正,谢~
我们都知道js是单线程语言,也就是只有一个线程,常称为主线程,在该线程中包含任务队列和执行栈
任务队列:
一些异步操作会将相关回调添加到任务队列中,而且不同的异步操作添加到队列的时间也不一样。
eg:
①onclick 等异步是当事件触发立即会将回调放到任务队列中。
②settimeout 会等到延迟时间到了再把回调放到任务队列中。
③像网络请求ajax是等到请求完成的时候再把回调放到任务队列中去。
执行栈:
执行栈就相当于一个全局方法,主方法,里面有个同步任务和异步任务,主线程在执行碰到同步任务就执行,碰到异步任务就将其回调放到任务队列中,执行完同步任务之后,就开始执行任务队列了,有一点要知道:
①一个事件循环中有一个或多个任务队列。
②每个事件循环都有一个microtask队列。
③macrotask队列就是我们常说的任务队列,microtask队列不是任务队列
④一个任务可以被放入到macrotask队列,也可以放入microtask队列
具体怎么划分看下面:
macrotasks(就是我们平常说的任务队列)和microtasks的划分:
macrotasks包括:setTimeout,setInterval,setInterval,setImmediate,requestAnimationFrame,I/O,UI rendering
microtasks包括:process.nextTick,Promises,Object.observe,MutationObserver
那么在执行队列(macrotasks队列==任务队列和microtasks队列)的时候,是怎样执行的呢?
microtask执行会在以下两种情况:
①任务队列(macrotask ==任务对列)回调后执行,前提条件是当前没有其他执行中的代码。
②每个任务队列(macrotask ==任务对列)末尾执行。
另外在处理microtask期间,如果有新添加的microtasks,也会被添加到队列的末尾并执行。
可以总结执行顺序如下:
开始 ----->取任务队列第一个task执行 ----->取microtask全部任务依次执行 ----->取任务队列下一个任务执行----->再次取出microtask全部任务执行-----> 。。。这样循环往复
伪代码大概表示了这个过程:
1 //js的任务队列和执行栈 2 let queue=[]; 3 let mircqueue=[]; 4 function Main()//浏览器js主线程 5 let event; 6 function executeStack()//执行栈 7 ..............;//执行栈中执行的同步代码 碰到宏观任务将回调放到任务队列中 下一次循环会执行 8 //执行完可执行的任务之后,立即执行微观任务,如下: 9 for(var i=0;i<mircqueue.length;i++)//取出所有microtask执行 10 event=queue.shift();//取出任务队列一个任务 11 event();//执行 12 13 while(true)//事件循环 14 if(queue.length>0) 15 event=queue.shift();//取出任务队列一个任务 16 event();执行 17 18 if(mircqueue.length>0) 19 for(var i=0;i<mircqueue.length;i++)//取出所有microtask执行 20 event=queue.shift();//取出任务队列一个任务 21 event();//执行 22 23 24 25 26 27 28 29 function Other()//浏览器其他的线程 30 function onxxx() 31 queue.push(new Task());//浏览器线程往任务队列中添加回调事件 32 //或者 33 mircqueue.push(new Task());//浏览器线程往microtask中添加回调事件 34 35 36 Main(); 37 Other();
那么我们来看一个例子:
eg1:
1 setTimeout(function() 2 console.log(1) 3 ,0); 4 new Promise(function(resolve) 5 console.log(2) 6 for( var i=100000 ; i>0 ; i-- ) 7 i==1 && resolve() 8 9 console.log(3) 10 ).then(function() 11 console.log(4) 12 ); 13 console.log(5);
结果是
2
3
5
4
1
eg2:
1 setTimeout(function() 2 console.log(1) 3 ,0); 4 setTimeout(function() 5 console.log(6) 6 ,2000); 7 new Promise(function(resolve) 8 console.log(2) 9 for( var i=100000 ; i>0 ; i-- ) 10 i==1 && resolve() 11 12 console.log(3) 13 ).then(function() 14 console.log(4); 15 setTimeout(function() 16 console.log(8) 17 ,1000) 18 ); 19 console.log(5);
这个执行结果是啥呢???想想
结果是:
2
3
5
4
1
8
6
总结一下,便于自己学习,也分享大家一起学习。(#^.^#)
以上是关于事件循环和任务队列的主要内容,如果未能解决你的问题,请参考以下文章
详解队列在前端的应用,深剖JS中的事件循环Eventloop,再了解微任务和宏任务