同步异步和Event loop事件循环

js 单线程模型

JavaScript 是单线程、非阻塞的一种语言,只有一个主线程,同时只能执行一个任务。

js 使用单线程是为了简单化

js 中的栈、堆和消息队列

存放的是调用函数的记录——调用帧

存放的是对象

消息队列

  • 包含待处理消息的队列
  • 每个消息都关联了一个回调函数,用以处理这个消息。

Event Loop

什么是事件循环Event Loop

Event Loop 是一种循环检查机制

  • 当主线程的任务执行完以后,就会去消息队列查看是否有满足条件的异步任务(js 将在消息队列中的任务称为异步任务)。
  • 如果有,就将该异步任务调入主线程成为同步任务,然后执行其关联的回调函数
  • 然后不断循环,如果任务队列的任务全部执行完了,那么程序就结束。

主线程

同步任务和异步任务

同步任务

是没有被挂起,在主线程里排队执行的任务

异步任务

分为宏任务和微任务

宏任务

包括:
包括整体代码 script、setTimeout、setInterval、setImmediate、I/O、UI rendering

微任务

包括:
promise.then, process.nextTick(node中)

宏任务的执行顺序在微任务之前

事件循环的过程

任务执行时,首先执行整体代码这个【宏任务】,将主线程同步任务清空之后,检查微任务列表,如果不为空则逐个加入到主线程进行执行;微任务列表清空以后,执行宏任务,如果宏任务执行完一个以后微任务列表不为空了,那么接着执行微任务,直到微任务清空,再执行宏任务,这样一直循环到所有的任务列表清空,事件循环结束。

示例:

console.log(1); //1.同步任务#1
setTimeout(function(){  //1.宏任务加入marcotask $1
    console.log(2);
    new Promise(function(resolve){ 
        console.log(3);
        setTimeout(function(){  //$3
            console.log(4);
        });
        resolve();
    }).then(function(){ //&2
        console.log(5);
    });
});
new Promise(function(resolve){  //1.promise 是同步任务!!!#2
        console.log(6);
        setTimeout(function(){  //1.加入宏任务队列 $2
            console.log(7);
        });
        resolve();
    }).then(function(){ //1.微任务加入microtask &1
        console.log(8);
    });
console.log(9); //1.同步任务#3

结果为 1 6 9 8 2 3 5 7 4

  • 首先执行同步任务 #1,遇到 setTimeout 宏任务 $1 加入到 macrotask 队列,遇到 promise 为同步任务 #2,直接执行,promise 执行遇到 setTimeout 宏任务 $2,加入 macrotask 队列,遇到 then() &1 加入微任务队列,然后执行同步任务 #3,第一次事件循环结束;
    此时:输出了结果 【1 6 9】
    macrotask:$1 $2
    microtask:&1
  • 执行微任务 &1,执行同步任务输出【8】,微队列清空,执行宏任务
  • 执行宏任务 $1,执行同步任务输出 【2】,遇到 promise 执行其同步任务,输出【3】,遇到 setTimeout 宏任务 $3,加入 macrotask,遇到 then() &2,加入 microtask$1 宏任务执行完毕,microtask 不为空,所以接下来执行微任务。
  • 执行微任务列表的任务:&2,输出 【5】,结束后微队列清空,执行宏任务
  • 执行 $2 宏任务,输出 【7】,执行结束
  • 执行 $3 宏任务,输出 【4】,执行结束
  • 此时所有队列清空,事件循环结束。

总结:先执行一个宏任务,再执行之下的所有微任务,如此循环;

posted @ 2020-03-22 12:42  秋秋秋白  阅读(205)  评论(0编辑  收藏  举报