news 2026/6/24 5:49:33

async/await 的原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
async/await 的原理

基础问答

问:async/await 的原理是什么?

答:关键字本身就是 Promise 的语法糖,依托于生成器函数 (Generator) 函数能力实现的。async 关键字标志这个函数为异步函数,并且将返回结果封装为一个 Promise,await 则是暂停当前执行,等待后续的异步操作完成后再恢复,相当于 Generator 的 yield 。只是在 Generator 中,需要手动调用 next() 触发执行, async 函数则内置该操作,自动根据 await 的异步结果执行后续函数步骤。

扩展延伸

在上面,提到了一个生成器函数(Generator),这个是 JavaScript 中的一种特殊函数,可以暂停和恢复函数执行。在平时的开发中,基本很少见到这个函数的使用,不过面试的时候,只要聊到了 async/await 内容,90% 以上的概率会问到生成器函数。

生成器函数使用 function* 语法定义,他会返回一个生成器对象,而不是和普通函数一样返回指定的结果,如下示例:

// 定义一个Generator函数,包含2个暂停点(yield)和1个返回值(return)

function* syncGenerator() {

console.log('1. 函数开始执行');

yield '第一个暂停结果'; // 第一个暂停点,返回值为'第一个暂停结果'

console.log('2. 函数恢复执行');

yield '第二个暂停结果'; // 第二个暂停点,返回值为'第二个暂停结果'

console.log('3. 函数即将结束');

return '最终返回结果'; // 函数执行完毕,返回最终结果

}

// 1. 调用Generator函数,返回迭代器(此时函数体未执行)

const genIterator = syncGenerator();

console.log('调用Generator后,函数未执行:', genIterator); // 输出:Generator {<suspended>}

// 2. 第一次调用next():执行到第一个yield,暂停

const result1 = genIterator.next();

console.log('第一次next()结果:', result1);

// 输出顺序:

// 1. 函数开始执行

// 第一次next()结果:{ value: '第一个暂停结果', done: false }(done=false表示未执行完毕)

// 3. 第二次调用next():从第一个yield恢复,执行到第二个yield,暂停

const result2 = genIterator.next();

console.log('第二次next()结果:', result2);

// 输出顺序:

// 2. 函数恢复执行

// 第二次next()结果:{ value: '第二个暂停结果', done: false }

// 4. 第三次调用next():从第二个yield恢复,执行到return,结束

const result3 = genIterator.next();

console.log('第三次next()结果:', result3);

// 输出顺序:

// 3. 函数即将结束

// 第三次next()结果:{ value: '最终返回结果', done: true }(done=true表示执行完毕)

// 5. 第四次调用next():函数已结束,后续调用均返回{ value: undefined, done: true }

const result4 = genIterator.next();

console.log('第四次next()结果:', result4); // 输出:{ value: undefined, done: true }

核心执行规则:

首次调用 Generator 函数:仅返回迭代器,函数体不执行;

每次调用 next ():函数从上次暂停位置继续执行,直到遇到下一个yield或return;

返回结果结构:next()返回的对象包含value(yield后的值或return的值)和done(布尔值,标识是否执行完毕);

执行完毕后:后续调用next(),done始终为true,value为undefined。

面试之外,你应该知道,Generator 函数的核心价值在于“异步流程控制”,即,通过yield暂停执行异步操作,等待异步结果返回后, 调用 next() 恢复执行。这就是 async/await 的底层逻辑雏形。

// 模拟接口请求(异步函数,返回Promise)

function fetchUser() {

return new Promise((resolve) => {

setTimeout(() => {

resolve({ id: 1, name: '前端面试' });

}, 1000);

});

}

function fetchOrders(userId) {

return new Promise((resolve) => {

setTimeout(() => {

resolve([{ orderId: '1001', goods: '面试指南' }]);

}, 1000);

});

}

// 定义异步Generator函数:用yield暂停异步操作

function* asyncGenerator() {

console.log('开始请求用户信息');

const user = yield fetchUser(); // 暂停,等待fetchUser的Promise完成

console.log('用户信息请求完成:', user);

console.log('开始请求订单信息');

const orders = yield fetchOrders(user.id); // 暂停,等待fetchOrders的Promise完成

console.log('订单信息请求完成:', orders);

return { user, orders }; // 最终返回结果

}

// 手动执行异步Generator函数(模拟async/await的自动执行器)

function runGenerator(genFn) {

const genIterator = genFn(); // 获取迭代器

// 定义递归执行函数

function handleNext(result) {

// 若Generator执行完毕,直接返回最终结果

if (result.done) {

return Promise.resolve(result.value);

}

// 若未执行完毕,处理yield返回的Promise(异步操作)

// result.value是yield后的值(此处为fetchUser/fetchOrders返回的Promise)

return Promise.resolve(result.value)

.then((res) => {

// 异步操作完成后,调用next(res)恢复执行,将异步结果作为yield的返回值

return handleNext(genIterator.next(res));

})

.catch((err) => {

// 捕获异步错误,调用throw(err)将错误传入Generator函数

return handleNext(genIterator.throw(err));

});

}

// 启动第一次执行

return handleNext(genIterator.next());

}

// 执行异步Generator函数

runGenerator(asyncGenerator)

.then((finalResult) => {

console.log('所有异步操作完成,最终结果:', finalResult);

})

.catch((err) => {

console.log('异步操作出错:', err);

});

async/await 本质是 Generator + 自动执行器的语法糖,二者核心逻辑可以一一对应上,只是 async/await 的封装大大简化了使用流程:

特性 Generator 函数 async/await

暂停 / 恢复标识 yield 关键字(手动标记暂停点) await关键字(自动标记暂停点)

执行控制 需手动调用迭代器的 next() 恢复执行 内置自动执行器,无需手动控制

异步结果处理 需手动用 Promise.resolve 等待异步结果 自动等待 await 后的 Promise 完成

错误处理 需手动调用 iterator.throw(err) 传入错误 用 try/catch 自动捕获错误

返回值 调用函数返回迭代器 调用函数返回 Promise

语法简洁度 较繁琐,需手动实现执行器 简洁,无需关注执行细节

面试追问

生成器函数?是怎么实现 async/await 的?

具体代码参考扩展延伸部分内容,要代码描述。

async/await 基础使用方式,使用 Promise 不是更好?为什么要用 async/await 关键字。

async function waitRequest() {

const resp = await axios.request('https://hello.com')

const data = resp.data;

return data、

}

可以使用Promise,这个是根据使用场景来的,async/await 只是将异步调用链转换成了同步代码,阅读维护起来更方便。

如封装一个等待延时,通常使用的就是 await + new Promise 来实现,只是多数情况下 Promise 伴随着的是比较长的调用链,带来阅读不便,此时转换成同步代码就清晰易读了。

如果 await 的表达式返回了 reject,需要捕获吗?要怎么捕获?

需要捕获,否则会触发“Uncaught (in Promise) Error”,中断代码执行,这个类似于 throw error。需要使用 try...catch 捕获 await 表达式产生的错误及reject。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/24 17:27:58

《构建游戏实时流失预警模型的核心逻辑》

玩家流失预警的关键痛点从来不是捕捉显性的行为衰减,而是解码藏在时序流转里的隐性流失信号—那些散落在跨模块交互、行为节奏变化中的序列异动,往往比单纯的在线时长缩短、任务参与度下降更早暴露玩家的离开倾向,也是实时预警模型能否实现“提前干预、精准留客”的核心突破…

作者头像 李华
网站建设 2026/6/23 19:52:29

两个步骤,打包war,tomcat使用war包

资源代码&#xff1a; https://download.csdn.net/download/hashiqimiya/92455258 如上 了解资源代码&#xff1a; 写了一个controller代码&#xff0c;控制接口对应该运行的函数。 package org.example.testproducttomcatwar;import org.springframework.web.bind.annotat…

作者头像 李华
网站建设 2026/6/24 16:57:52

idea修改maven的刷新引入依赖快捷键

在 IntelliJ IDEA 里&#xff0c;Load Maven Changes 对应的是当你修改 pom.xml 或者依赖后&#xff0c;手动刷新 Maven 项目的操作。你也可以给它自定义快捷键。具体步骤如下&#xff1a;1. 打开快捷键设置Windows/Linux: File → Settings → KeymapmacOS: IntelliJ IDEA → …

作者头像 李华
网站建设 2026/6/23 19:51:17

纯电动汽车Simulink仿真模型建模详细步骤。 通过文档的形式,跟着文档一步一步操作,既可以...

纯电动汽车Simulink仿真模型建模详细步骤。 通过文档的形式&#xff0c;跟着文档一步一步操作&#xff0c;既可以提高自己的建模能力&#xff0c;又可以对整个建模思路进行借鉴&#xff0c;形成设计能力。 附带模型。纯电动汽车仿真模型在Simulink里搭建就像搭乐高——找准核心…

作者头像 李华
网站建设 2026/6/23 19:48:46

同花顺平衡多空看图操作多空理论

{}多空:50,COLORFFFFFF,POINTDOT; J:(C-LLV(L,9))/(HHV(H,9)-LLV(L,9))*100,colormagenta; K:SMA(J,3,1),colorwhite; D:SMA(K,3,1),coloryellow; 动能:100 * (LLV(LOW,60)-EMA(CLOSE,3))/(LLV(LOW,60)-HHV(HIGH,60)),colorligray,LINETHICK2; 多:IF(动能>多空,动能,DRAWNUL…

作者头像 李华
网站建设 2026/6/23 19:52:38

通达信222222测试帖别下载

{} Z1:STRCAT(【,STRCAT(CODE,STKNAME));Z2:STRCAT( 行业&#xff1a;,HYBLOCK);Z3:STRCAT( 地域&#xff1a;,DYBLOCK);Z4:STRCAT(STRCAT( 概念&#xff1a;,GNBLOCK),】);Z5:STRCAT(Z1,Z2);Z6:STRCAT(Z3,Z4);Z7:STRCAT(Z5,Z6);DRAWTEXT_FIX(1,0.35,0.030,0,Z7),COLORGREEN…

作者头像 李华