用这道题巩固你的EventLoop知识(再谈EventLoop)

2020-11-19  本文已影响0人  喜剧之王爱创作

关于EventLoop

说起EventLoop(事件循环),这真是一个JS中经久不衰的话题啊,从我个人浅显的阅历来看,几乎每一个博主或者公众号作者的作品中都会有这样一篇关于事件循环讲解的,当然了,我也不例外,我也曾写下一篇见到异步就懵逼?带你认识JS Event Loop(事件循环)。其实关于EventLoop的知识,网上的文章铺天盖地,这篇文章我也不会重复去讲那些“略显基础”的知识点,同样,我还是用我个人的白话来总结一下,啥是EventLoop。

当然了,两句话是不可能完全准确的概括的,大概就是这么个意思,如果再往深说点,那大概就是

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。

如果你掌握了上面的知识,可能对于一些简单的问题和常见的业务逻辑有了一个处理手段。也算是比较实用,比如下面的一些代码

console.log('a') // 这里可能是一段实际业务
setTimeOut( () => {
  console.log('b') // 这里可能是一段实际业务
}, 0)

我们通过上面的代码,对代码的执行顺序有了一个明确的控制。再或者,在react中,我们知道setState是一个“伪异步”(只是看起来像异步,因为react的合成事件导致),所以我们经常会有setState后拿不到最新状态的情况发生,当然了recat在setState中是设有回调函数的,我们可以拿到,但是如果不用回调函数,那我们要如何做呢?这时候,也会用到事件循坏的东西。比如下面的代码

setState({
   oldstate: newstate
})
setTimeOut( () => {
    console.log(newstate) // 这样就可以拿到newState了,如果不加定时器,那就还是旧值
}, 0)

当然了,如果你了解了上面这些东西,平时开发应用是没问题了,可偏偏有一些“面试题”,让你抓狂,让你不知所措。绕来绕去的头晕,但往往,它能把你绕头晕,恰恰说明你对他的知识掌握的还不是很全面牢靠。下面,我用我个人出的一道题来更细致的说一下这个事件循环。

小编出题

Promise.resolve().then(() => {
    console.log('p1')
    setTimeout(() => {
        console.log('t1')
        Promise.resolve().then(() => {
            console.log('p4')
        })
    }, 0)
})

setTimeout(() => {
    console.log('t2')
    Promise.resolve().then(() => {
        console.log('p2')
        setTimeout(() => {
            console.log('t3')
        }, 0)
    })
    Promise.resolve().then(() => {
        console.log('p5')
    })
}, 0)

求上面打印结果。

小编聊知识点

实际中,我们不会遇到使用这么复杂的异步逻辑去折磨自己,但如果你会这道题,那么关于事件循坏的大部分知识和题目,你都没有问题了。本文,我会假设你已经掌握了EventLoop的基本知识,那么我再补充一点。

讲到这里,其实就是给大家又划了两个重点,意在,不要再简单的说“同步先执行,异步后执行,微任务先执行,宏任务后执行”了。这样说是不全面的,也是存在一定的误解的,容易给你搞懵,比如上面这道题。在我补充完上面的知识点后,大家应该有一个疑问,什么是“一个一个”,什么是“一队一队”?这里我还是用自己的白话来说

好了,上面白话过后,那么我们直接看题吧,我来一步步分析

小编分析

讲到这里,我想大家明白这种复杂的事件循坏该怎么解决了吧?也应该对事件循坏有了一个更全面的了解了。好了!接下来直接看看吧!

上一篇下一篇

猜你喜欢

热点阅读