JavaScript异步编程Async/Await详解

B站影视 韩国电影 2025-05-27 17:45 3

摘要:Øasync 函数:声明一个异步函数,隐式返回Promise对象。若函数返回非Promise值,会被自动包装为Promise.resolve(value)。

JavaScript 异步编程 Async/Await 使用详解:从原理到最佳实践

一、Async/Await 基础

核心概念

Ø async 函数:声明一个异步函数,隐式返回 Promise 对象。若函数返回非 Promise 值,会被自动包装为 Promise.resolve(value)

javascript

async function fetchData {

return 'data';

}

// 等效于:

function fetchData {

return Promise.resolve('data');

}

Ø await 表达式:暂停异步函数的执行,等待 Promise 解决。若等待的值非 Promise,则转换为 Promise.resolve(value)

javascript

async function example {

const result = await 42; // 等同于 await Promise.resolve(42)

console.log(result); // 42

}

错误处理

Ø try/catch 捕获异常await 后的 Promise 若被 reject,会抛出异常,可通过 try/catch 捕获。

javascript

async function fetchWithError {

try {

const data = await fetch('invalid-url');

} catch (error) {

console.error('Fetch failed:', error);

}

}

Ø 链式 .catch:通过返回的 Promise 处理错误。

javascript

fetchWithError.catch(error => console.error('Top-level error:', error));

二、Async/Await 原理

生成器与执行器

Ø 生成器函数 (function*):通过 yield 暂停执行,手动调用 next 恢复。

Ø 自动执行器:Async/Await 本质是生成器 + 自动执行器的语法糖,类似 co 库的实现。

javascript

// 模拟 Async/Await 的生成器实现

function* generatorExample {

const data = yield fetchData;

console.log(data);

}

// 自动执行器(简化版)

function run(generator) {

const iterator = generator;

function handle(result) {

if (result.done) return;

result.value.then(res => handle(iterator.next(res)));

}

handle(iterator.next);

}

run(generatorExample);

事件循环与微任务

Ø await 的暂停机制:遇到 await 时,将后续代码作为微任务加入队列,主线程继续执行其他同步任务。

Ø 执行顺序示例

javascript

console.log('Start');

async function test {

console.log('Before await');

await Promise.resolve;

console.log('After await');

}

test;

console.log('End');

// 输出顺序:Start → Before await → End → After await

三、最佳实践与常见问题

并行执行优化

Ø 错误示例:串行等待导致性能损失。

javascript

async function slowExample {

const a = await fetchA; // 等待A完成

const b = await fetchB; // 再等待B完成(总耗时 = A + B)

}

Ø 正确做法:使用 Promise.all 并行执行。

javascript

async function fastExample {

const [a, b] = await Promise.all([fetchA, fetchB]); // 并行执行(总耗时 ≈ Max(A, B))

}

循环中的异步处理

Ø for 循环串行执行

javascript

async function processArray(array) {

for (const item of array) {

await processItem(item); // 逐个处理

}

}

Ø map + Promise.all 并行执行

javascript

async function processArrayParallel(array) {

await Promise.all(array.map(item => processItem(item))); // 并行处理所有项

}

错误处理封装

Ø 高阶函数统一处理:减少重复 try/catch

javascript

function withErrorHandling(fn) {

return async (...args) => {

try {

return await fn(...args);

} catch (error) {

console.error('Error in', fn.name, error);

throw error; // 可选择是否继续抛出

}

};

}

const safeFetch = withErrorHandling(fetchData);

避免常见陷阱

Ø forEach 中的陷阱:无法正确等待异步操作。

javascript

// 错误示例:所有操作并行启动,但无法等待完成

array.forEach(async item => await processItem(item));

// 正确做法:使用 for...of 或 Promise.all

Ø 顶层 await:仅在 ES Modules 中可用,避免在非模块脚本中使用。

四、总结与扩展

核心优势:以同步形式编写异步代码,提升可读性和可维护性。适用场景:适用于需要顺序执行、复杂错误处理的异步流程。进阶技巧:结合 Promise.race 处理超时、利用 async 函数作为 Express/Koa 中间件等。

通过理解原理、遵循最佳实践,可充分发挥 Async/Await 的优势,编写高效、健壮的异步 JavaScript 代码。

来源:老客数据一点号

相关推荐