Node.js中async/await与微任务宏任务执行机制详解
本文详细解析Node.js中async和await关键字的使用规则,包括async函数始终返回Promise及await暂停执行的特性。同时深入探讨JS事件循环机制,区分宏任务与微任务的执行时机,阐明Promise.then和process.nextTick优先于大部分异步代码执行的原理,帮助开发者理解异步编程底层逻辑。
async 和 await 关键字
async 和 await 是 ES2017 标准中引入的关键字,旨在简化 Promise 的使用流程。
async 关键字
async 关键字的使用相对简单,主要需注意以下三点:
- async 用于修饰一个 function
- 被 async 修饰的函数,其返回值始终是一个 Promise 对象。
- 函数内部返回的任何值,都会自动被包装在一个 resolved 状态的 Promise 中。
// async 用于修饰一个 function
// 1. async 修饰的函数,总是返回一个 Promise 对象
// 2. 函数的返回值,将自动包装在 resolve 的 promise 中
// 1. async 修饰的函数,总是返回一个 Promise 对象
async function fn() {
// 2. 函数的返回值,将自动包装在 resolve 的 promise 中
return '哈哈哈';
}
// 以后看一下博客文章之类的东西,里面会有一些变量使用 :foo 和 bar , 无意义;
const foo = fn();
console.log(foo);
foo.then(res => {
console.log(res);
});
// 注意: async修饰的函数被称为异步函数,可他不是异步执行;
console.log('我是最后一行代码');await 关键字
await 关键字的使用较为繁琐,注意事项较多。首先,await 只能出现在 async 函数内部。它的作用是使 JavaScript 引擎暂停当前函数的执行,直到 Promise 完成并返回结果。语法如下:
let value = await promise对象; // 等待promise对象的结果,然后将结果赋值给 value
由于 await 需要等待 Promise 执行完毕,因此它会暂停当前函数的执行,但不会影响其他同步任务的运行。
因此,对 await 的总结如下四点:
- await 只能出现在异步函数中!
- await 能停止代码执行,让后面的同步代码,先执行;
- await 后面跟随的是一个 promise 对象;
- await 返回的是: Promise 对象中的 then() 中的回调函数中的参数 res;
// 定义一个方法,为的就是返回一个 Promise 对象,让下面的await使用;
async function getPromise() {
return '哈哈哈';
}
console.log(1);
// 1.await只能出现在async修饰的函数中!
async function fn() {
console.log(2);
// 2.await后面跟随的是一个promise对象;
// 3.await返回的是: Promise对象中的then()中的回调函数中的参数res;
const str = await getPromise();
console.log(str);
// 4.await能停止代码执行,让后面的同步代码,先执行;
console.log(3);
}
// 调用
fn();
console.log(4);
// // 以前用法:
// axios().then(res => {
// res.data.map()
// });
// // 以后用法:
// async function name() {
// let res = await axios();
// res.data.map();
// }async 和 await 解决回调地狱
// async 和 await 解决回调地狱也要用到 then-fs ,因为他直接返回 Promise 对象;
// 导入 then-fs
import thenFs from 'then-fs';
// await 一定要出现在异步函数中
async function fn() {
let str1 = await thenFs.readFile('./txt/a.txt', 'utf8');
console.log(str1);
let str2 = await thenFs.readFile('./txt/b.txt', 'utf8');
console.log(str2);
let str3 = await thenFs.readFile('./txt/c.txt', 'utf8');
console.log(str3);
}
// 调用函数
fn();JS执行机制(事件循环)
- js代码开始执行后,主线程执行栈中会把任务分为两类.
- 一类是同步任务, 一类是异步任务; 主线程执行栈优先执行同步任务,
- 异步任务会被放入特定的处理程序中,满足条件后,被放到消息(任务/事件)队列中,
- 主线程执行栈中所有的同步任务执行完毕之后,通过事件循环去消息(任务/事件)队列中,
- 挑选优先满足条件的程序,放入主线程执行栈中执行。事件循环,周而复始,一直执行。
微任务和宏任务
在ES3 以及以前的版本中,JavaScript本身没有发起异步请求的能力,也就没有微任务的存在。在ES5之后,JavaScript引入了Promise,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务了。 Tick会触发浏览器渲染,Promise不会触发,所以更加轻量级,多使用;
宏任务
(macro)task,可以理解是每次执行栈执行的代码就是一个宏任务
- 主线程上的执行栈中所有的代码块
- setTimeout
- setInterval
- Ajax
- 事件
微任务
微任务(microtask)是宏任务中的一个部分,它的执行时机是在同步代码执行之后,下一个宏任务执行之前。
总结起来,微任务有:
- Promise.then
- process.nextTick(Node.js 环境)
宏任务和微任务执行机制
JS优先执行同步任务,然后执行微任务,最后执行宏任务。
总结:Promise中的then()比大部分异步代码,优先执行!
// 结论: 如果同一时间既有宏任务又有微任务触发,那么优先执行微任务;
// 宏任务是宿主发起的会触发重构,比较浪费资源,后执行;
// 微任务是js解释器发起的不会触发重构,比较节省资源,先执行;
// 宏任务
setTimeout(() => {
//执行后 回调一个宏事件
console.log('1')
}, 0)
// 同步代码
console.log('2');
// 同步代码
new Promise((resolve) => {
console.log('3');
resolve()
// 微任务
}).then(() => {
console.log('4');
// 微任务
}).then(()=>{
console.log('5')
})
// 同步代码
console.log('6')
// 2 3 6 4 5 1到此这篇关于Node.js中的async 和 await 关键字微任务和宏任务的文章就介绍到这了,更多相关Node.js async 和 await 内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
在 NestJS 中使用管道验证数据与守卫控制访问权限
2026-11-05 12:43:41
Node.js后端生成高强度随机字符串的方法
2026-11-04 16:29:54
Node.js环境中怎么使用axios或http模块发送GET请求
2026-11-03 21:57:15
Node.js环境下怎么实现JS反混淆自动化?常用库与CLI工具推荐
2026-11-03 21:15:54
解决JS逆向常见报错:缺少DOM环境导致代码运行失败
2026-11-03 20:41:59
