笔试题——JavaScript事件循环机制(event loop、macrotask、microtask)

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

内容简介:今天做了一道笔试题觉得很有意义分享给大家,题目如下:JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的首先来看一个小小的demo

今天做了一道笔试题觉得很有意义分享给大家,题目如下:

setTimeout(()=>{
    console.log('A');
},0);
var obj={
    func:function () {
        setTimeout(function () {
            console.log('B')
        },0);
        return new Promise(function (resolve) {
            console.log('C');
            resolve();
        })
    }
};
obj.func().then(function () {
    console.log('D')
});
console.log('E');复制代码

JavaScript 都知道它是一门单线程的语言,这也就意味着 JS 无法进行多线程编程,但是 JS 当中却有着无处不在的 异步 概念 。要完全理解异步,就需要了解 JS 的运行核心—— 事件循环(event loop)。

一、什么是事件队列?

首先来看一个小小的demo

console.log('start');
setTimeout(()=>{
    console.log('A');
},1000);
console.log('end');
//start
//end
//A复制代码

js执行之后,程序输出 'start' 和 'end',在大约1s之后输出了 'A' 。那我们就有疑问了?为什么A不在end之前执行呢?

这是因为 setTimeout 是一个异步的函数。意思也就是说当我们设置一个延迟函数的时候,当前脚本并不会阻塞,它只是会在浏览器的事件表中进行记录,程序会继续向下执行。当延迟的时间结束之后,事件表会将回调函数添加至 事件队列(task queue) 中,事件队列拿到了任务过后便将任务压入 执行栈(stack) 当中,执行栈执行任务,输出 'A'。

事件队列 是一个存储着待执行任务的队列,其中的任务严格按照 时间先后顺序 执行,排在队头的任务将会率先执行,而排在队尾的任务会最后执行。事件队列每次仅执行一个任务,在该任务执行完毕之后,再执行下一个任务。执行栈则是一个类似于函数调用栈的运行容器,当执行栈为空时,JS 引擎便检查事件队列,如果不为空的话,事件队列便将第一个任务压入执行栈中运行。

那么我将这个例子做一个小小的改动看一看:

console.log('start');
setTimeout(()=>{
    console.log('A');
},0);
console.log('end');
//start
//end
//A复制代码

可以看出,我们将settimeout第二个参数设置为0后,'A' 也总是会在 'end' 之后输出。所以究竟发生了什么?这是因为 setTimeout 的回调函数只是会被添加至 事件队列 ,而不是立即执行。由于当前的任务没有执行结束,所以 setTimeout 任务不会执行,直到输出了 'end' 之后,当前任务执行完毕,执行栈为空,这时事件队列才会把 setTimeout 回调函数压入执行栈执行。

二、Promise的含义和基本用法?

所谓 Promise ,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

写一个小demo看一下Promise的运行机制:

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi!');
// Promise
// Hi!
// resolved复制代码

上面代码中,Promise 新建后 立即执行 ,所以首先输出的是 Promise 。然后, then 方法指定的回调函数,将在当前脚本 所有同步任务执行完才会执行 ,所以 resolved 最后输出。

三、 Macrotasks和Microtasks

Macrotasks和Microtasks 都属于上述的异步任务中的一种,他们分别有如下API:

macrotasks: setTimeout, setInterval, setImmediate, I/O, UI rendering

microtasks: process.nextTick, Promise, MutationObserver

setTimeout的macrotask, 和 Promise的microtask 有哪些不同,先来看下代码如下:

console.log(1);
setTimeout(function(){
  console.log(2);
}, 0);
Promise.resolve().then(function(){
  console.log(3);
}).then(function(){
  console.log(4);
});

//1
//3
//4
//2复制代码

如上代码可以看到, Promise 的函数代码的异步任务会 优先setTimeout 的延时为0的任务先执行。

原因是任务队列分为 macrotasks 和 microtasks, 而promise中的then方法的函数会被推入到microtasks队列中,而setTimeout函数会被推入到macrotasks

任务队列中,在每一次事件循环中, macrotask 只会 提取一个执行 ,而 microtask一直 提取,直到microsoft队列 为空 为止。

也就是说如果某个microtask任务被推入到执行中,那么当主线程任务执行完成后,会循环调用该队列任务中的下一个任务来执行,直到该任务队列到最后一个任务为止。

而事件循环每次只会入栈一个macrotask, 主线程 执行完成该任务后又会检查 microtasks 队列并完成里面的所有任务后再执行 macrotask 的任务。

四、分析本题目

setTimeout(()=>{
    console.log('A');
},0);
var obj={
    func:function () {
        setTimeout(function () {
            console.log('B')
        },0);
        return new Promise(function (resolve) {
            console.log('C');
            resolve();
        })
    }
};
obj.func().then(function () {
    console.log('D')
});
console.log('E');复制代码

1、首先 setTimeout  A 被加入到 事件队列 中  ==>  此时 macrotasks 中有[‘A’];

2、obj.func()执行时,setTimeout B 被加入到 事件队列 中  ==> 此时 macrotasks 中有[‘A’,‘B’];

3、接着return一个Promise对象,Promise 新建后 立即执行 执行console.log('C'); 控制台 首次 打印‘C’;

4、然后, then 方法指定的回调函数,被加入到 microtasks 队列,将在当前脚本所有同步任务执行完才会执行。 ==> 此时 microtasks 中有[‘D’];

5、然后继续执行当前脚本的同步任务,故控制台第 二次 输出‘E’;

6、此时所有同步任务执行完毕,如上所述先检查 microtasks 队列 完成其中所有任务,故控制台第 三次 输出‘D’;

7、最后再执行 macrotask 的任务,并且按照入队列的时间顺序,控制台第 四次 输出‘A’,控制台第 五次 输出‘B’。

五、执行js代码

笔试题——JavaScript事件循环机制(event loop、macrotask、microtask)

分析与实际符合,NICE!

参考文章: www.cnblogs.com/tugenhua070…

还有阮老师的promise介绍: es6.ruanyifeng.com/?search=pro…

文章本人原创,转载请评论;

前端菜鸟对JavaScript的理解还有很多不足,如有错误欢迎大家指出来;

喜欢的点个赞把!


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

查看所有标签

猜你喜欢:

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

Visual Thinking

Visual Thinking

Colin Ware / Morgan Kaufmann / 2008-4-18 / USD 49.95

Increasingly, designers need to present information in ways that aid their audiences thinking process. Fortunately, results from the relatively new science of human visual perception provide valuable ......一起来看看 《Visual Thinking》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具