首页 > 语言 > JavaScript > 正文

前端js中的事件循环eventloop机制详解

2024-05-06 15:39:28
字体:
来源:转载
供稿:网友

前言

我们知道 js 是单线程执行的,那么异步的代码 js 是怎么处理的呢?例如下面的代码是如何进行输出的:

console.log(1);setTimeout(function() { console.log(2);}, 0);new Promise(function(resolve) { console.log(3); resolve(Date.now());}).then(function() { console.log(4);});console.log(5);setTimeout(function() { new Promise(function(resolve) {  console.log(6);  resolve(Date.now()); }).then(function() {  console.log(7); });}, 0);

在不运行的情况可以先猜测下最终的输出,然后展开我们要说的内容。

1. 宏任务与微任务

依据我们多年编写 ajax 的经验:js 应该是按照语句先后顺序执行,在出现异步时,则发起异步请求后,接着往下执行,待异步结果返回后再接着执行。但他内部是怎样管理这些执行任务的呢?

在 js 中,任务分为宏任务(macrotask)和微任务(microtask),这两个任务分别维护一个队列,均采用先进先出的策略进行执行!同步执行的任务都在宏任务上执行。

宏任务主要有:script(整体代码)、setTimeout、setInterval、I/O、UI 交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)。

微任务主要有:Promise.then、 MutationObserver、 process.nextTick(Node.js 环境)。

具体的操作步骤如下:

    从宏任务的头部取出一个任务执行; 执行过程中若遇到微任务则将其添加到微任务的队列中; 宏任务执行完毕后,微任务的队列中是否存在任务,若存在,则挨个儿出去执行,直到执行完毕; GUI 渲染; 回到步骤 1,直到宏任务执行完毕;

这 4 步构成了一个事件的循环检测机制,即我们所称的eventloop。

回到我们上面说的代码:

console.log(1);setTimeout(function() { console.log(2);}, 0);new Promise(function(resolve) { console.log(3); resolve(Date.now());}).then(function() { console.log(4);});console.log(5);setTimeout(function() { new Promise(function(resolve) {  console.log(6);  resolve(Date.now()); }).then(function() {  console.log(7); });}, 0);

执行步骤如下:

    执行 log(1),输出 1; 遇到 setTimeout,将回调的代码 log(2)添加到宏任务中等待执行; 执行 console.log(3),将 then 中的 log(4)添加到微任务中; 执行 log(5),输出 5; 遇到 setTimeout,将回调的代码 log(6, 7)添加到宏任务中; 宏任务的一个任务执行完毕,查看微任务队列中是否存在任务,存在一个微任务 log(4)(在步骤 3 中添加的),执行输出 4; 取出下一个宏任务 log(2)执行,输出 2; 宏任务的一个任务执行完毕,查看微任务队列中是否存在任务,不存在; 取出下一个宏任务执行,执行 log(6),将 then 中的 log(7)添加到微任务中; 宏任务执行完毕,存在一个微任务 log(7)(在步骤 9 中添加的),执行输出 7;
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选