JavaScript中async和await的使用及队列详情

作者:闭包旅人时间:2026-10-25 14:04:23浏览:165

本文详细解析JavaScript中async和await关键字的使用方法及底层执行队列机制。通过剖析宏任务与微任务的调度规则,结合具体代码示例,阐明异步操作的执行顺序,帮助开发者深入理解异步编程模型及面试中常见的队列问题。

一、关于宏任务与微任务的队列基础概念,可参阅往期内容:

[JavaScript的事件循环机制]

宏任务与微任务在前端面试中频繁出现,涵盖口头及笔试环节

1.async与await概念解析

async:

  • 通过async关键字声明的函数属于AsyncFunction构造函数的实例,在async函数内部可使用await接收Promise实例
  • 在开发实践中,async与await关键字可用于简化异步操作的编写

await:

  • await操作符接收一个Promise对象,且必须与异步函数async function配合使用
  • await表达式会暂停当前async function的执行,直至Promise处理完成
  • 若Promise正常处理(fulfilled),其回调的resolve函数参数将作为await表达式的值,并继续执行
  • 若Promise处理异常(rejected),await表达式会将Promise的异常原因抛出
  • 若await操作符后的表达式值非Promise,则直接返回该值本身

2.async与await基本用法

/**
 * async 函数是使用async关键字声明的函数。
 * async 函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。
 * async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。
 *
 * await  操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用。
 * await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理 (fulfilled),其回调的 resolve 函数参数作为 await 表达式的值,继续执行
 * async function。
 * 若 Promise 处理异常 (rejected),await 表达式会把 Promise 的异常原因抛出。
 * 另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。
 *
 *
 * */
// 模拟请求接口
function userInfo() {
	return new Promise((resolve) => {
		setTimeout(() => {
			resolve("zhangsan");
		}, 2000);
	});
}

// 接收请求的返回值
async function fetchUserInfo() {
	let res = await userInfo();
	console.log(res);
}
fetchUserInfo(); // zhangsan

// 不是异步promise
let testFn = function test(){}
async function notPromise() {
	var str = await testFn;
	console.log(str); // function test(){}
}
notPromise();

二、async与await结合Promise在面试中涉及的队列问题

function userInfo() {
	return new Promise((resolve) => {
		setTimeout(() => {
			resolve(`接口返回值---------------1`);
		}, 2000);
	});
}

console.log("1");
let p1 = new Promise((resolve, reject) => {
	resolve("p1");
});
let p2 = new Promise((resolve, reject) => {
	resolve("p2");
});
async function getUserInfo() {
    console.log("2");
    
    p1.then((res) => {
    	console.log(res);
    });
    var awaitRes = await userInfo();
    console.log(awaitRes); // 接口返回值---------------1
    
    p2.then((res) => {
    	console.log(res);
    });
    
    console.log("3");
}
console.log("4");
getUserInfo(); // 异步方法,加入任务队列执行
console.log("5");

/**
 *
 * 执行顺序
 *
 * 1
 * 4
 * 2
 * 5
 * p1
 * 接口返回值---------------1
 * 3
 * p2
 *
 *
 * */
  • 同步任务1、4执行
  • getUserInfo作为异步方法,优先执行同步代码2
  • p1、userInfo方法及p2这三个Promise对象被放入异步队列,且await后的代码会阻塞后续代码执行,因此3也作为异步任务,置于await之后执行
  • 此时,先执行5
  • 所有同步代码执行完毕后,从队列中执行异步任务,p1、awaitRes---->接口返回值---------------1
  • 值得注意的是,由于await会阻塞同步代码执行,因此await执行完成后,先执行其之后被阻塞的同步代码,执行完毕后才执行p2这个Promise异步任务

因此整个代码块的执行顺序为:

1、4、2、5、p1、接口返回值---------------1、3、p2

三、总结

async与await作为ECMAScript的新特性,目前更多场景应用于前端获取后端接口及进行某些异步操作

至此,关于JavaScript中async和await的使用及队列详情的文章介绍完毕,更多相关JavaScript中async和await内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章