1

浏览器中的eventLoop 与node中的eventLoop

node11之前是不一样,node11之后,与浏览器一样

js单线程存在的问题

  1. js是单线程的,处理任务是一件接着一件处理,所以如果一个任务需要处理很久的话,后面的任务就会被阻塞
  2. 所以js通过Event Loop事件循环的方式解决了这个问题,在了解事件循环前,我们需要了解一些关键词

    什么是stack,queue,heap,event loop

  3. stack(栈,执行栈):先进后出
  4. queue(队列,回调队列)先进先出
  5. heap(堆,一堆代码):存储obj对象

clipboard.png

Event Loop的具体流程

  1. 堆里面有同步和异步的方法
  2. 这些方法,放到栈里,栈是先进后出的执行
  3. 同步的话一个一个的执行,碰到异步的方法,也会执行,但是不会执行完,而是先交给webapis处理,多个异步,会形成一个队列,先进先出
  4. 等到同步的方法执行完后,把wepapi中的异步方法取出来,放到栈中执行

     <script>
         console.log(1)
         setTimeout(() => {
             console.log(2)
             setTimeout(() => {
                 console.log(3)
             }, 0)
         }, 0)
         setTimeout(() => {
             console.log(4)
         }, 0)
         console.log(5)
     </script>

    上面的代码最后输出1,5,2,4,3,执行过程:
    只有console.log(2)执行完成,执行栈再次清空时,才会从回调队列取出console.log(3)

1,输出1,将2push进回调队列

2,将4push进回调队列

3,输出5

4,清空了执行栈,读取输出2,发现有3,将3push进回调队列

5,清空了执行栈,读取输出4

6,清空了执行栈,读取输出3

Macrotask(宏任务)、Microtask(微任务)

  1. Microtask(微任务)虽然是队列,但并不是一个一个放入执行栈,而是当执行栈请空,会执行全部
  2. Microtask(微任务)队列中的任务,最后才是取回调队列的第一个Macrotask(宏任务)
    ···
    <script>

     setTimeout(() => {
         console.log(1)
     })
     Promise.resolve().then(() => {
         console.log(2)
         Promise.resolve().then(() => {
             console.log(3)
         })
     })
     Promise.resolve().then(() => {
         console.log(4)
     })

    </script>
    ···
    上面的执行过程是:
    1,将setTimeout给push进宏任务
    2,将then(2)push进微任务
    3,将then(4)push进微任务
    4,任务队列为空,取出微任务第一个then(2)压入执行栈
    5,输出2,将then(3)push进微任务
    6,任务队列为空,取出微任务第一个then(4)压入执行栈
    7,输出4
    8,任务队列为空,取出微任务第一个then(3)压入执行栈
    9,输出3
    10,任务队列为空,微任务也为空,取出宏任务中的setTimeout(1)
    11,输出1

async/await

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}

等价于

async function async1() {
    console.log('async1 start');
    Promise.resolve(async2()).then(() => {
                console.log('async1 end');
        })
}
demo
async function a1 () {
    console.log('a1 start')
    await a2() //相当于同步,直接打印
    console.log('a1 end')
}
async function a2 () {
    console.log('a2')  //相当于同步,直接打印
}

console.log('script start')

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

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

a1()

let promise2 = new Promise((resolve) => {
    resolve('promise2.then')
    console.log('promise2')
})

promise2.then((res) => {
    console.log(res)
    Promise.resolve().then(() => {
        console.log('promise3')
    })
})
console.log('script end')

打印顺序

script start
a1 start
a2
promise2
script end
promise1
a1 end
promise2.then
promise3
setTimeout

参考

https://juejin.im/post/5a6309...
https://github.com/Advanced-F...
可视化

last


渣渣辉
1.3k 声望147 粉丝