深入理解 Event Loop

栏目: JavaScript · 发布时间: 7年前

内容简介:众所周知,JavaScript(以下简称 JS) 是单线程语言,在 html5 中增加了 web workers,web workers 是新开了线程执行的,那么 JS 还是单线程的吗?当然是,为什么要设计成单线程?网上有很多说法,大部分都说是多个线程同时对一个dom操作(同时修改dom内容,一个线程增加属性,一个线程删除属性),会非常混乱,当然如果支持多线程就会相应的就要加入多线程的锁机制,那么 JS 就变得非常复杂了,想想 JS 最开始设计的初衷就是用于用户交互,而且当时的原始需求是:功能不需要太强,语

众所周知,JavaScript(以下简称 JS) 是单线程语言,在 html5 中增加了 web workers,web workers 是新开了线程执行的,那么 JS 还是单线程的吗?当然是,为什么要设计成单线程?

网上有很多说法,大部分都说是多个线程同时对一个dom操作(同时修改dom内容,一个线程增加属性,一个线程删除属性),会非常混乱,当然如果支持多线程就会相应的就要加入多线程的锁机制,那么 JS 就变得非常复杂了,想想 JS 最开始设计的初衷就是用于用户交互,而且当时的原始需求是:功能不需要太强,语法较为简单,容易学习和部署,Brendan Eich 只用了10天,就设计完成了这种语言的第一版,因此也不可能加入多线程这么复杂的技术。

即使现在支持 web workers,由于没有多线程的机制,web workers 和执行线程只能通过 postMessage 来通信,而且由于没有锁,web workers 无法访问 window 和 document 对象。

JS 的单线程是指一个浏览器进程中只有一个 JS 的执行线程,即同一时刻内只会有一段代码在执行。

Micro-Task 与 Macro-Task

单线程如何实现异步?JS 设计了一个事件循环的方式。所有的代码执行均按照事件循环的方式进行。

事件循环中分两种任务:一个是宏任务(Macro-Task),另一个是微任务(Micro-Task)。常见的宏任务和微任务如下。

宏任务:script(整体代码)、setTimeout、setInterval、requestAnimationFrame、I/O、事件、MessageChannel、setImmediate (Node.js) 微任务:Promise.then、 MutaionObserver、process.nextTick (Node.js)

事件循环按下图的方式进行。

深入理解 Event Loop

注意: 宏任务执行完后,需要清空当前微任务队列后才回去执行下一个宏任务,如果微任务里面产生了新的微任务,仍然会在当前事件循环里面被执行完,后面会举例说明。

来个示例验证下上面的流程。

<script>
    console.log(1);

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

    Promise.resolve().then(function promise1() {
        console.log(3);
        setTimeout(function timeout2() {
            console.log(4);
            Promise.resolve().then(function promise2() {
                console.log(5);
            });
        }, 0);
        return Promise.resolve()
            .then(function promise3() {
                console.log(6);
                return Promise.resolve().then(function promise4() {
                    console.log(7);
                });
            })
            .then(function promise5() {
                console.log(8);
            });
    })
    console.log(9);
</script>

<script>
    console.log(10);
    setTimeout(function timeout3() {
        console.log(11);
    }, 0);
    Promise.resolve().then(function promise6() {
        console.log(12);
    });
</script>
复制代码

按照上面流程梳理下执行流程:

[script1, script2]
[script2]
[script2, timeout1]
[promise1]
[script2, timeout1, timeout2]
[promise3]
[promise4]
[promise4,promise5]
[promise5]
[ timeout1, timeout2]
[timeout1, timeout2, timeout3]
[promise6]
[ timeout2, timeout3]
[ timeout3]
[promise2]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Big Java Late Objects

Big Java Late Objects

Horstmann, Cay S. / 2012-2 / 896.00元

The introductory programming course is difficult. Many students fail to succeed or have trouble in the course because they don't understand the material and do not practice programming sufficiently. ......一起来看看 《Big Java Late Objects》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换