IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> nodejs--事件环、宏任务和微任务 -> 正文阅读

[JavaScript知识库]nodejs--事件环、宏任务和微任务

目录

一、事件环

1.1 初识事件环

1.2 NodeJS事件环和浏览器事件环区别

1.3 NodeJS中的任务队列

1.4 其他

二、宏任务和微任务

2.1 初识宏任务和微任务

2.2 宏任务和微任务

2.3 常见的宏任务和微任务

2.4 注意点:

?


?

一、事件环

1.1 初识事件环

和浏览器中一样NodeJS中也有事件环(Event?Loop),但是由于执行代码的宿主环境和应用场景不同,所以两者的事件环也有所不同

1.2 NodeJS事件环和浏览器事件环区别

任务队列个数不同:

浏览器事件环有2个事件队列(宏任务队列和微任务队列)

NodeJS事件环有6个事件队列

微任务队列不同,

  • 浏览器事件环中有专门存储微任务的队列
  • NodeJS事件环中没有专门存储微任务的队列

微任务执行时机不同,

  • 浏览器事件环中每执行完一个宏任务都会去清空微任务队列
  • NodeJS事件环中只有同步代码执行完毕和其它队列之间切换的时候回去清空微任务队列

微任务优先级不同,

  • 浏览器事件环中如果多个微任务同时满足执行条件,?采用先进先出
  • NodeJS事件环中如果多个微任务同时满足执行条件,?会按照优先级执行

示例:

Promise.resolve().then(function() {
    console.log("Promise");
});
process.nextTick(function() {
    console.log("process.nextTick1");
});
process.nextTick(function() {
    console.log("process.nextTick2");
});
process.nextTick(function() {
    console.log("process.nextTick3");
});


1.3 NodeJS中的任务队列

????┌───────────────────────┐

┌>?│timers??????????│执行setTimeout()?和?setInterval()中到期的callback

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

│??│pending?callbacks│执行系统操作的回调,?如:tcp,?udp通信的错误callback

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

│??│idle,?prepare???│只在内部使用

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

│??│poll????????????│执行与I/O相关的回调

????│??????????????????(除了close回调、定时器回调和setImmediate()之外,几乎所有回调都执行);

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

│??│check???????????│执行setImmediate的callback

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

└─┤close?callbacks?│执行close事件的callback,例如socket.on("close",func)

????└───────────────────────┘


?

????┌───────────────────────┐

┌>?│timers??????????│执行setTimeout()?和?setInterval()中到期的callback

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

│??│poll????????????│执行与I/O相关的回调

????│??????????????????(除了close回调、定时器回调和setImmediate()之外,几乎所有回调都执行);

│??└──────────┬────────────┘

│??┌──────────┴────────────┐

└─┤check???????????│执行setImmediate的callback

????└───────────────────────┘

注意点:

  • 和浏览器不同的是没有宏任务队列和微任务队列的概念
  • 宏任务被放到了不同的队列中,?但是没有队列是存放微任务的队列
  • 微任务会在执行完同步代码和队列切换的时候执行

什么时候切换队列?

当队列为空(已经执行完毕或者没有满足条件回到)

或者执行的回调函数数量到达系统设定的阈值时任务队列就会切换

注意点:

在NodeJS中process.nextTick微任务的优先级高于Promise.resolve微任务

????????????┌───────────────────────┐

????????????│????????????????同步代码

????????????└──────────┬────────────┘

??????????????????????????????????│

??????????????????????????????????│?<----?满足条件微任务代码

??????????????????????????????????│

????????????┌──────────┴────────────┐

????????┌>?│timers??????????│执行setTimeout()?和?setInterval()中到期的callback

????????│??└──────────┬────────────┘

????????│????????????????????????│

????????│????????????????????????│?<----?满足条件微任务代码

????????│????????????????????????│

????????│??┌──────────┴────────────┐

????????│??│poll????????????│执行与I/O相关的回调

????????│??│??????????????????(除了close回调、定时器回调和setImmediate()之外,几乎所有回调都执行);

????????│??└──────────┬────────────┘

????????│????????????????????????│

????????│????????????????????????│?<----?满足条件微任务代码

????????│????????????????????????│

????????│??┌──────────┴────────────┐

????????└─┤check???????????│执行setImmediate的callback

????????????└───────────────────────┘

示例 :

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

Promise.resolve().then(function() {
    console.log("Promise");
});

console.log("同步代码 Start");

process.nextTick(function() {
    console.log("process.nextTick");
});

setImmediate(function() {
    console.log("setImmediate");
});
console.log("同步代码 End");

执行流程,

注意点:

  • 执行完poll,?会查看check队列是否有内容,?有就切换到check
  • 如果check队列没有内容,?就会查看timers是否有内容,?有就切换到timers
  • 如果check队列和timers队列都没有内容,?为了避免资源浪费就会阻塞在poll

示例,

setTimeout(function() {
    console.log("setTimeout1");
    // p1
    Promise.resolve().then(function() {
        console.log("Promise1");
    });
    // n1
    process.nextTick(function() {
        console.log("process.nextTick1");
    });
});
console.log("同步代码 Start");
setTimeout(function() {
    console.log("setTimeout2");
    // p2
    Promise.resolve().then(function() {
        console.log("Promise2");
    });
    // n2
    process.nextTick(function() {
        console.log("process.nextTick2");
    });
});
console.log("同步代码 End");

执行流程:


1.4 其他

注意点:?如下代码输出的结果是随机的

????????在NodeJS中指定的延迟时间是有一定的误差的,?所以导致了输出结果随机的问题

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


二、宏任务和微任务

2.1 初识宏任务和微任务

? JS是单线程的:JS中的代码都是串行的,?前面没有执行完毕后面不能执行

执行顺序:

  • 程序运行会从上至下依次执行所有的同步代码
  • 在执行的过程中如果遇到异步代码会将异步代码放到事件循环中
  • 当所有同步代码都执行完毕后,?JS会不断检测?事件循环中的异步代码是否满足条件
  • 一旦满足条件就执行满足条件的异步代码


2.2 宏任务和微任务

在JS的异步代码中又区分"宏任务(MacroTask)"和"微任务(MicroTask)"

宏任务(MacroTask):?宏/大的意思,?可以理解为比较费时比较慢的任务

微任务(MicroTask):?微/小的意思,?可以理解为相对没那么费时没那么慢的任务

2.3 常见的宏任务和微任务

i.宏任务 (MacroTask):

setTimeout,?setInterval,?setImmediate(IE独有)...

setlmmediate的基本用法:

setImmediate(function() {
            console.log("setImmediate");
        });
console.log("同步代码Start");
console.log("同步代码End");

setImmediate和setTimeout,?setInterval区别:

setImmediate不能设置延迟时间,?并且只能执行一次;IE独有,也就是只能IE浏览器里才能生效

ii. 微任务(MicroTask)

Promise,?MutationObserver?,process.nextTick(node独有)?...

MutationObserver的基本用法:

MutationObserver是专门用于监听节点的变化

<div></div>
<button class="add">添加节点</button>
<button class="del">删除节点</button>
        let oDiv = document.querySelector("div");
        let oAddBtn = document.querySelector(".add");
        let oDelBtn = document.querySelector(".del");
        oAddBtn.onclick = function() {
            let op = document.createElement("p");
            op.innerText = "我是段落";
            oDiv.appendChild(op);
        }
        oDelBtn.onclick = function() {
            let op = document.querySelector("p");
            oDiv.removeChild(op);
        }

        //监听--只要监听到了你添加或者是删除节点就会打印如下的语句
        let mb = new MutationObserver(function() {
            console.log("执行了");
        });

        //选择监听的对象
        // 这里表示监听oDiv子节点的变化
        mb.observe(oDiv, {
            "childList": true
        });

        console.log("同步代码Start");
        console.log("同步代码End");


2.4 注意点:

  • 所有的宏任务和微任务都会放到自己的执行队列中,?也就是有一个宏任务队列和一个微任务队列
  • 所有放到队列中的任务都采用"先进先出原则",?也就是多个任务同时满足条件,?那么会先执行先放进去的

完整执行顺序:

  • 从上至下执行所有同步代码
  • 在执行过程中遇到宏任务就放到宏任务队列中,遇到微任务就放到微任务队列中
  • 当所有同步代码执行完毕之后,?就执行微任务队列中满足需求所有回调
  • 当微任务队列所有满足需求回调执行完毕之后,?就执行宏任务队列中满足需求所有回调
  • ...?...

示例1,

        // 1.定义一个宏任务
        setTimeout(function() {
            console.log("setTimeout1");
        }, 0);

        // 2.定义一个微任务
        Promise.resolve().then(function() {
            console.log("Promise1");
        });

        console.log("同步代码Start");

        Promise.resolve().then(function() {
            console.log("Promise2");
        });

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

        console.log("同步代码End");

执行流程:

注意点:

每执行完一个宏任务都会立刻检查微任务队列有没有被清空,?如果没有就立刻清空

示例2,

        // 1.定义一个宏任务
        setTimeout(function() {
            console.log("setTimeout1");
            // 2.定义一个微任务 p1
            Promise.resolve().then(function() {
                console.log("Promise1");
            });
            // 2.定义一个微任务 p2
            Promise.resolve().then(function() {
                console.log("Promise2");
            });
        }, 0);

        // 1.定义一个宏任务
        setTimeout(function() {
            console.log("setTimeout2");
            // 2.定义一个微任务 p3
            Promise.resolve().then(function() {
                console.log("Promise3");
            });
            // 2.定义一个微任务 p4
            Promise.resolve().then(function() {
                console.log("Promise4");
            });
        }, 0);

执行流程:

示例3,

         // 1.定义一个宏任务
        setTimeout(function() {
            console.log("setTimeout1");
            // 2.定义一个微任务 p2
            Promise.resolve().then(function() {
                console.log("Promise2");
            });
            // 2.定义一个微任务 p3
            Promise.resolve().then(function() {
                console.log("Promise3");
            });
        }, 0);
        // 2.定义一个微任务 p3
        Promise.resolve().then(function() {
            console.log("Promise1");
            // s2
            setTimeout(function() {
                console.log("setTimeout2");
            });
            // s3
            setTimeout(function() {
                console.log("setTimeout3");
            });
        });

执行流程:

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:37:04  更:2021-12-01 17:37:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:03:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码