【async 和 await】
async
是 JavaScript 中用于定义异步函数的关键字。它通常与 await
一起使用,用于简化异步操作(如网络请求、文件读写、定时器等)的代码编写。
为了更好地理解 async
,我们需要先了解 JavaScript 中的异步编程。
1. 什么是异步编程?
JavaScript 是单线程的,意味着它一次只能执行一个任务。如果某个任务需要很长时间(如网络请求),传统的同步代码会阻塞后续代码的执行,导致页面卡顿。
为了解决这个问题,JavaScript 引入了异步编程。异步编程允许我们在等待某个任务完成的同时,继续执行其他任务。
常见的异步操作包括:
- 网络请求(如
axios
、fetch
)。 - 文件读写(如 Node.js 中的
fs.readFile
)。 - 定时器(如
setTimeout
、setInterval
)。
2. 传统的异步编程方式
在 async/await
出现之前,JavaScript 主要通过以下方式处理异步操作:
回调函数(Callback)
function fetchData(callback) {
setTimeout(() => {
callback('数据加载完成');
}, 1000);
}
fetchData((data) => {
console.log(data); // 1 秒后输出:数据加载完成
});
缺点:容易导致回调地狱(Callback Hell),代码难以维护。
Promise
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('数据加载完成');
}, 1000);
});
}
fetchData().then((data) => {
console.log(data); // 1 秒后输出:数据加载完成
});
缺点:虽然解决了回调地狱问题,但代码仍然不够直观。
3. async/await
的引入
async/await
是 ES2017(ES8)引入的语法糖,用于简化异步代码的编写。它基于 Promise
,但让异步代码看起来更像同步代码。
async
关键字
- 用于声明一个异步函数。
- 异步函数会隐式返回一个
Promise
对象。 - 如果函数返回值不是
Promise
,它会被自动包装成Promise
。
await
关键字
- 用于等待一个
Promise
完成。 - 只能在
async
函数内部使用。 - 它会暂停当前函数的执行,直到
Promise
完成。
4. async/await
的使用示例
以下是一个简单的例子,展示了如何使用 async/await
处理异步操作:
function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('数据加载完成');
}, 1000);
});
}
async function main() {
console.log('开始加载数据');
const data = await fetchData(); // 等待 fetchData 完成
console.log(data); // 1 秒后输出:数据加载完成
console.log('数据加载完毕');
}
main();
输出结果:
开始加载数据
(等待 1 秒)
数据加载完成
数据加载完毕
5. async/await
的优点
- 代码更简洁:避免了回调地狱和复杂的
Promise
链。 - 更易读:异步代码看起来像同步代码,逻辑更清晰。
- 错误处理更方便:可以使用
try/catch
捕获异步操作中的错误。
6. 错误处理
在 async/await
中,可以使用 try/catch
捕获异步操作中的错误。
async function fetchDataWithError() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('数据加载失败');
}, 1000);
});
}
async function main() {
try {
console.log('开始加载数据');
const data = await fetchDataWithError(); // 这里会抛出错误
console.log(data);
} catch (error) {
console.error('捕获到错误:', error); // 输出:捕获到错误: 数据加载失败
}
}
main();
7. async
函数的返回值
async
函数总是返回一个 Promise
对象。如果函数返回值不是 Promise
,它会被自动包装成 Promise
。
async function foo() {
return 'Hello';
}
foo().then((result) => {
console.log(result); // 输出:Hello
});
8. 并行执行异步操作
如果需要同时执行多个异步操作,可以使用 Promise.all
。
async function fetchData1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('数据1');
}, 1000);
});
}
async function fetchData2() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('数据2');
}, 1500);
});
}
async function main() {
const [data1, data2] = await Promise.all([fetchData1(), fetchData2()]);
console.log(data1, data2); // 1.5 秒后输出:数据1 数据2
}
main();
9. 总结
async
用于声明异步函数,函数返回值会被包装成Promise
。await
用于等待Promise
完成,只能在async
函数内部使用。async/await
让异步代码更简洁、易读。- 可以使用
try/catch
捕获异步操作中的错误。 - 如果需要并行执行多个异步操作,可以使用
Promise.all
。
通过 async/await
,你可以更轻松地编写和管理异步代码。如果还有其他问题,欢迎随时提问!