资讯专栏INFORMATION COLUMN

JavaScript事件循环(Event Loop)

justjavac / 1620人阅读

摘要:关于和,因为本身就是的语法糖。实际上是一个让出线程的标志。队列清空,进入执行栈,打印,程序运行完毕。完整结果如下该结果基于版本。因为标准有所改变,所以稍老版本的浏览器结果可能不一致。

任务队列

首先我们要知道关于JavaScript的一些规则:

JavaScript是被设计成单线程的

JavaScript的任务分为同步任务和异步任务

同步任务都在主线程上执行,形成一个执行栈。当主线程执行完之后,运行微任务(micro-task)队列的任务直到为空,更新UI渲染(会根据浏览器的逻辑,决定要不要马上执行更新),然后再运行宏任务(macro-task)队列的任务直到为空......流程如下:

(主线程上的执行栈同步任务,可以视为是第一个macro-task队列)
 macro-task -> micro-task(如果存在) -> 更新UI渲染

如此无限循环上面的流程,是为JavaScript的Event Loop机制。

宏任务

宏任务(macro-task),宏任务队列可以有一个或者多个。每个任务都有一个任务源(task source),源自同一个任务源的 task 必须放到同一个任务队列,从不同源来的则被添加到不同队列。

宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.

微任务

微任务(micro-task),微任务在渲染更新前,macro-task之后执行。
关于async和await,因为async await 本身就是promise+generator的语法糖。所以await后面的代码是microtask。实际上await是一个让出线程的标志。await后面的表达式会先执行一遍,将await后面的代码加入到microtask中,然后就会跳出整个async函数来执行后面的代码。

微任务:process.nextTick, Promise, Object.observer, MutationObserver,await.

举例
        async function async1() {
            console.log("async1 start");
            await async2();
            console.log("async1 end");
        }
        async function async2() {
            console.log("async2");
        }

        console.log("script start");

        setTimeout(function () {
            console.log("setTimeout");
        }, 0)

        async1();

        new Promise(function (resolve) {
            console.log("promise1");
            resolve();
        }).then(function () {
            console.log("promise2");
        });
        console.log("script end");

流程如下:

console打印script start

setTimeout,是异步宏任务,进入macro-task setTimeout队列

async1(), async await函数,在await之前是同步任务,直接执行,打印async1 start

await async2(),await后面的表达式会先执行一遍,打印async2

await 下面的代码视为promise.then,进入micro-task promise队列,跳出async1()

new Promise,promise内,.then之前的代码是直接执行的,所以打印promise1

.then内函数进入micro-task promise队列后

console,直接打印script end

主线程执行栈运行完并清空了,micro-task进入执行栈,分别按顺序执行打印async1 endpromise2

micro-task队列清空,macro-task进入执行栈,打印setTimeout,程序运行完毕。

完整结果如下:

/**
 *script start
 *async1 start
 *async2
 *promise1
 *script end
 *async1 end
 *promise2
 *setTimeout
 */

该结果基于chrome 版本 72.0.3626.121。因为async await标准有所改变,所以稍老版本的浏览器结果可能不一致。

参考:
https://jakearchibald.com/201...
https://github.com/Advanced-F...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109013.html

相关文章

  • 初窥JavaScript事件机制的实现(一)—— Node.js事件驱动实现概览

    摘要:如果当前没有事件也没有定时器事件,则返回。相关资料关于的架构及设计思路的事件讨论了使用线程池异步运行代码。下一篇初窥事件机制的实现二中定时器的实现 在浏览器中,事件作为一个极为重要的机制,给予JavaScript响应用户操作与DOM变化的能力;在Node.js中,事件驱动模型则是其高并发能力的基础。 学习JavaScript也需要了解它的运行平台,为了更好的理解JavaScript的事...

    lavor 评论0 收藏0
  • JavaScript 事件循环(译文JavaScript Event Loop

    摘要:事件循环了解了在引擎中是如何工作了之后,来看下如何使用异步回调函数来避免代码。从回调函数被放入后秒钟,把移到中。由于事件循环持续地监测调用栈是否已空,此时它一注意到调用栈空了,就调用并创建一个新的调用栈。 听多了JavaScript单线程,异步,V8,便会很想去知道JavaScript是如何利用单线程来实现所谓的异步的。我参考了一些文章,了解到一个很重要的词汇:事件循环(Event L...

    K_B_Z 评论0 收藏0
  • JavaScript Event loop 事件循环

    摘要:阶段有两个主要功能也会执行时间定时器到达期望时间的回调函数执行事件循环列表里的函数当进入阶段并且没有其余的定时器,那么如果事件循环列表不为空,则迭代同步的执行队列中的函数。如果没有,则等待回调函数进入队列并立即执行。 Event Loop 本文以 Node.js 为例,讲解 Event Loop 在 Node.js 的实现,原文,JavaScript 中的实现大同小异。 什么是 Eve...

    luckyyulin 评论0 收藏0
  • 关于浏览器Event Loop

    摘要:的宿主最开始本身就是浏览器,处理用户的交互事件。既然是单线程的,那就意味着任务需要排队,只有前一个任务执行完毕,下一个任务才能开始,于是就有了任务队列。事件循环有两种用于浏览上下文的事件循环和用于的事件循环。 最近看到Event Loop这个词出现的频率有点高,于是查阅各方资料在此记录一下。 先不说概念,我们来看段代码: console.log(script start); setT...

    youkede 评论0 收藏0
  • JS异步详解 - 浏览器/Node/事件循环/消息队列/宏任务/微任务

    js异步历史 一个 JavaScript 引擎会常驻于内存中,它等待着我们把JavaScript 代码或者函数传递给它执行 在 ES3 和更早的版本中,JavaScript 本身还没有异步执行代码的能力,引擎就把代码直接顺次执行了,异步任务都是宿主环境(浏览器)发起的(setTimeout、AJAX等)。 在 ES5 之后,JavaScript 引入了 Promise,这样,不需要浏览器的安排,J...

    awesome23 评论0 收藏0
  • JavaScript执行机制、事件循环

    摘要:曾经的理解首先,是单线程语言,也就意味着同一个时间只能做一件事,那么为什么不是多线程呢这样还能提高效率啊假定同时有两个线程,一个线程在某个节点上编辑了内容,而另一个线程删除了这个节点,这时浏览器就很懵逼了,到底以执行哪个操作呢所以,设计者把 Event Loop曾经的理解 首先,JS是单线程语言,也就意味着同一个时间只能做一件事,那么 为什么JavaScript不是多线程呢?这样还能提...

    rose 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<