事件循环究竟是什么东东?附例题

Posted on 2019-03-15 12:27  xxxxxxxx  阅读(176)  评论(0)    收藏  举报

 

其实事件循环Event loop的概念不难,难点在于你能判断事件的执行顺序。

还是先说说概念吧。我的理解的是JS里面事件分为宏任务和微任务,宏任务先于微任务执行。宏任务就是整段的script啊setTimeout啊setInterval这些,微任务是Promis.then方法这些。

同时任务还可以分为同步任务和异步任务。

执行任务的时候同步任务进入主线程处理,异步任务进入Event Table并注册回调函数,再把回调函数加到Event Queue里面,其中宏任务和微任务不是一个广场滴。

等到主线程里的同步任务执行完之后再读取Event  Queue里的任务执行。因为回调函数里面也可能会包含不同的任务,因此会循环执行上述操作。

这就是我理解的事件循环了~但是纸上谈兵是不够的,我在网上找几道题来增强理解吧。

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');
首先输出整段代码script start 遇到setTimeout添加到setTimeout队列里,遇到Promise执行其构造函数输出promise,遇到第二个setTimeout加到队列中,然后promise.then加到微任务队列里,遇到script end执行。主线程执行结束执行微任务,再执行setTimeout队列。

 

new Promise(resolve => {
    resolve(1);
    Promise.resolve().then(() => console.log(2));
    console.log(4)
}).then(t => console.log(t));
console.log(3);
构造promise对象执行构造函数4,第一个then和第二个then依次加入微任务队列中,执行整段script的代码3,主线程处理完毕执行微任务,输出2,再1.

 

  • setTimeout(()=>{
  • console.log('A');
  • },0);
  • var obj={
  • func:function () {
  • setTimeout(function () {
  • console.log('B')
  • },0);
  • return new Promise(function (resolve) {
  • console.log('C');
  • resolve();
  • })
  • }
  • };
  • obj.func().then(function () {
  • console.log('D')
  • });
  • console.log('E');

C E D A B


async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')

 

 

 console.log('start');

      Promise.resolve().then(()=>{
        console.log('promise1')
      }).then(()=>{
        console.log('promise2');
      });

      setImmediate(()=>{
        console.log('setImmediate');
      });

      setTimeout(()=>{
        console.log('setTimeout');
      }, 0);

      console.log('end'); 
 start end promise1 promise2 setImmediate setTimeout 或者start end promise1 promise2 setTimeout setImmediate、
 setImmediate和setTimeout在主线程上随机执行 在异步里前者优先
https://segmentfault.com/a/1190000013102056?utm_medium=referral&utm_source=tuicool
 

答案为

首先全部输出first,然后全部输出second
 
JavaScript 是单线程的,setTimeout 设置的是异步任务,会放在 macrotask 里面,等待执行栈的代码执行完毕之后才会执行 macrotask 里面的异步任务,所以这里会等待 for 循环执行完毕才会执行定时器设置的任务。