什么是Event Loop

2019-07-08  本文已影响0人  被代码耽误的裁缝

Event Loop

一、进程和线程

1.进程:

资源分配的最小单位;应用程序的执行实例,每一个进程都是由私有的虚拟地址空间、代码、数据和其他系统资源所组成;进程拥有独立的堆栈空间和数据段,每当启动一个新的进程必须分配给他独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段。

2.线程:

程序执行的最小单位;线程是进程内的一个独立执行单元,在不同的线程之间是可以共享进程资源的;

线程拥有独立的堆栈空间,但是共享数据段,他们彼此之间使用相同的地址空间,共享大部分数据,比进程更节俭,开销比较小,切换速度也比进程快,效率高。

二、同步任务和异步任务

我可以将任务分为同步任务和异步任务,但是这并不准确。

1.同步任务:

同步任务就是在主线程上排队执行的任务,只能执行完一个再执行下一个。

2.异步任务:

异步任务则不进入主线程,而是现在 event table 中注册函数,当满足触发条件后,才可以进入任务队列来执行。只有任务队列通知主线程说,我这边异步任务可以执行了,这个时候此任务才会进入主线程执行。

3.举例

console.log("a");
setTimeout(function(){
    console.log("b")
},1000)
console.log("c")

//"a" "c" "b"
/*
    1.console.log("a")是同步任务,进入主线程执行,打印"a"
    2.setTimeout 是异步任务,先被放入 event table 中注册,1000ms 之后进入任务队列
    3.console.log("c")是同步任务,进入主线程执行,打印"c"
    当"a","c"被打印后,主线程去事件队列中找到 setTimeout 里的函数,并执行,打印"b"
*/

三、宏任务和微任务

同步任务和异步任务的划分其实并不准确,准确的分类方式是宏任务(Macrotask)和微任务(Microtask)。

1.宏任务

宏任务包括:script(整体代码)、setTimeout、setInterval、setImmediate、I/O、UI rendering。

2.微任务

微任务包括:process.nextTick、Promise、MutationObserver(html5新特性)。

这种分类的执行方式就是,执行一个宏任务,过程中遇到微任务时,将其放到微任务的事件队列里,当前宏任务执行完后,会查看微任务的事件队列,依次执行里面的微任务。如果还有宏任务的话,再重新开启宏任务…

通俗的可以理解为,首先执行script(整体代码)宏任务,从上往下执行,遇到宏任务放入宏任务队列,遇到微任务放入微任务队列 => 执行微任务队列的任务,然后执行宏任务队列的第一个任务

=>执行script(整体代码)宏任务,从上往下执行,遇到宏任务放入宏任务队列,遇到微任务放入微任务队列
=>查看微任务队列并执行
=>执行宏任务队列的第一个任务
=>查看微任务队列并执行
=>执行宏任务队列的第二个任务
=>查看微任务队列并执行
=>执行宏任务队列的第三个任务
=>查看微任务队列并执行
....

3.举例

setTimeout(function(){
    console.log("a")
})
new Promise(function(resolve){
    console.log("b")
    for(var i=0;i<10000;i++){
        i==99 && resolve();
    }
}).then(function(){
    console.log("c")
})
console.log("d")
//"b" "d" "c" "a"
/*
    1.首先执行 script 下的宏任务,遇到 setTimeout,将其放入宏任务的队列里
    2.遇到 Promise,new Promise 直接执行,打印"b"
    3.遇到 resolve=>then 方法,是微任务,将其放入微任务的队列里
    4.遇到 console.log("d"),直接打印"d"
    5.本轮宏任务执行完毕,查看微任务,发现 then 方法里的函数,打印"c"
    6.本轮 event loop 全部完成
    7.下一轮循环,先执行宏任务,发现宏任务队列中有一个 setTimeout,打印"a"
*/
console.log("a")
setTimeout(function(){
    console.log("b")
    process.nextTick(function(){
        console.log("c")
    })
    new Promise(function(resolve){
        console.log("d")
        resolve();//如果没有执行 resolve,那么 then 方法不执行
    }).then(function(){
        console.log("e")
    })
})
process.nextTick(function(){
    console.log("f")
})
new Promise(function(resolve){
    console.log("g")
    resolve()//如果没有执行 resolve,那么 then 方法不执行
}).then(function(){
    console.log("h")
})
setTimeout(function(){
    console.log("i")
    process.nextTick(function(){
        console.log("j")
    })
    new Promise(function(resolve){
        console.log("k")
        resolve()
    }).then(function(){
        console.log("l")
    })
})
//"a" "g" "f" "h" "b" "d" "i" "k" "c" "j" "e" "l"
//第一轮宏任务打印:"a" "g"
//第一轮微任务打印:"f" "h"
//第二轮宏任务打印:"b" "d" 
//第二轮微任务打印:"c" "e"
//第三轮宏任务打印:"i" "k"
//第三轮微任务打印:"j" "l"
console.log("script start")
setTimeout(function () {
    console.log("a")
    setTimeout(function () {
        console.log("b")
    })
    new Promise(function (resolve) {
        console.log("c")
        resolve();
    }).then(function () {
        console.log("d")
        setTimeout(function () {
            console.log("e")
        })
    })
})
new Promise(function (resolve) {
    console.log("f")
    resolve()
}).then(function () {
    console.log("g")
})
setTimeout(function () {
    console.log("h")
    setTimeout(function () {
        console.log("i")
    })
    new Promise(function (resolve) {
        console.log("j")
        resolve();
    }).then(function () {
        console.log("k")
        setTimeout(function () {
            console.log("l")
            new Promise(function (resolve) {
                console.log("m")
                resolve()
            }).then(function () {
                console.log("n")
                setTimeout(function () {
                    console.log("o")
                })
            })
        })
    })
})
//执行一个宏任务,检查并执行微任务队列

//最终打印顺序为: 
//"script start" "f" "g" "a" "c" "h" "j" "k" "b" "e" "i" "l" "m" "n" "o"
上一篇 下一篇

猜你喜欢

热点阅读