分享

js执行任务流程最详细讲解

 爱睡觉的魄罗 2022-09-05 发布于北京

1、首先我们要明白一个概念,js它是单线程的一门语言。

它是基于事件循环的。事件循环大致分为以下几个步骤:

所有同步任务都在主线程上执行,形成一个执行栈

主线程之外,还存在一个"任务队列"(task queue)。

只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。主线程不断重复上面的第三步。



因为console.log是同步代码,所以会立刻放到主线程中执行,当我们异步请求数据时,console.log()执行代码未放到异步请求中,就会在主线程中执行,自然获取不到数据,而如果用setTimeout包裹console.log(),它会放到我们的任务队列里边,等待主线程的活干完了,再拿到主线程执行,如下代码所示:


任务队列里面又分为宏任务与微任务

微任务,也称job

       通常用于在当前正在执行的脚本之后直接发生的事情,比如对一系列的行为做出反应,或者做出一些异步的任务,而不需要新建一个全新的task。只要执行栈没有其他javascript在执行,在每个task结束时, 微任务队列就会在回调后处理。在 微任务 期间排队的其他 微任务 将被添加到这个队列的末尾

      常见的 微任务 有 MutationObsever 、 Promise.then  、$nextTiock

宏任务

       作用是为了让浏览器能够从内部获取javascript / dom的内容并确保执行栈能够顺序进行。调度是随处可见的,例如解析HTML,获得鼠标点击的事件回调等等。

       常见的 宏任务 有 setTimeout、MessageChannel、postMessage、setImmediate;



因为promise.then  $nextTick()是个微任务,setTimeout是个宏任务,所以先输出promise。


2.定时器的任务编排

这里我们发现,定时器虽然是异步任务,但js执行是单线程,当时间结束后,定时器会被放到任务队列挂着,当主线程执行时间过长,定时器时间到了会先挂起来,一旦主线任务结束,就立即执行定时器。

 如,一个for循环执行结束需要5000ms而定时器执行2000ms,2000ms过了,定时器就会被放入任务队列,5000ms的主线任务结束后,立即执行定时器,而不是在等2000ms执行定时器回调。


3.Promise微任务处理逻辑

Promise 是同步代码立刻执行,然后执行下面的同步代码console.log('hello’),同步代码执行完后到微任务里面找到promise.then()的console.log() 来执行,最后执行宏任务setTimeout

接下来我们看如下代码,看起来有点复杂,但是我们记住一个原则,“先执行同步代码,再执行微任务,最后执行宏任务”,这样就会清晰很多

4、DOM渲染任务

如下代码,我们在渲染DOM 前执行了一个非常耗时的for循环,因为DOM渲染也是一个同步任务,而for循环在DOM渲染之前,所以会将for循环执行完后再渲染DOM。

这时候页面会有很长一段时间的空白,然后才渲染h1标签和文字

解决办法:

将js代码放到最后,这样就完美解决了



5.任务共享内存

时间到了,会将其回调任务放到我们的任务队列当中,虽然时间一样,但是还是遵循从上而下的规则,首先输出中的++i,然后再加一次

6、三角塔构成

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多