推荐答案
async/await 是 ECMAScript 2017 (ES8) 引入的语法糖,用于简化异步代码的编写。它基于 Promise,允许开发者以同步的方式编写异步代码,从而避免回调地狱(Callback Hell)和复杂的 Promise 链。
async关键字用于声明一个异步函数。异步函数会自动返回一个Promise对象。如果函数内部返回一个值,这个值会被包装成一个Promise对象;如果函数内部抛出异常,返回的Promise对象会被拒绝(rejected)。await关键字用于等待一个Promise对象的解析(resolve)。它只能在async函数内部使用。await会暂停当前异步函数的执行,直到Promise对象被解析或拒绝。如果Promise被解析,await会返回解析后的值;如果Promise被拒绝,await会抛出异常。
本题详细解读
1. async 函数
async 函数是使用 async 关键字声明的函数。它总是返回一个 Promise 对象。如果函数内部返回一个非 Promise 的值,这个值会被自动包装成一个 Promise 对象。如果函数内部抛出异常,返回的 Promise 对象会被拒绝。
async function foo() {
return 42;
}
foo().then(result => console.log(result)); // 输出: 42在上面的例子中,foo 函数返回 42,但由于它是一个 async 函数,返回值会被自动包装成一个 Promise 对象。因此,我们可以使用 .then() 方法来处理这个 Promise。
2. await 表达式
await 关键字用于等待一个 Promise 对象的解析。它只能在 async 函数内部使用。await 会暂停当前异步函数的执行,直到 Promise 对象被解析或拒绝。
async function bar() {
const result = await new Promise((resolve) => {
setTimeout(() => resolve('Hello, World!'), 1000);
});
console.log(result); // 输出: Hello, World!
}
bar();在这个例子中,await 表达式会暂停 bar 函数的执行,直到 Promise 被解析。解析后的值会被赋值给 result 变量,然后继续执行后续代码。
3. 错误处理
在 async/await 中,可以使用 try/catch 语句来捕获和处理 await 表达式中可能抛出的异常。
// www.javascriptcn.com code example
async function baz() {
try {
const result = await new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('Something went wrong!')), 1000);
});
console.log(result);
} catch (error) {
console.error(error.message); // 输出: Something went wrong!
}
}
baz();在这个例子中,await 表达式等待的 Promise 被拒绝,抛出一个错误。这个错误会被 catch 块捕获并处理。
4. 并行执行
如果需要并行执行多个异步操作,可以使用 Promise.all 结合 await 来实现。
// www.javascriptcn.com code example
async function parallel() {
const [result1, result2] = await Promise.all([
new Promise(resolve => setTimeout(() => resolve('Result 1'), 1000)),
new Promise(resolve => setTimeout(() => resolve('Result 2'), 2000))
]);
console.log(result1, result2); // 输出: Result 1 Result 2
}
parallel();在这个例子中,Promise.all 会等待所有 Promise 对象都被解析后,返回一个包含所有解析值的数组。await 表达式会等待这个数组的返回,并将其解构赋值给 result1 和 result2。
5. async/await 的优势
- 代码简洁:
async/await使得异步代码看起来像同步代码,避免了回调地狱和复杂的Promise链。 - 错误处理:可以使用
try/catch语句来捕获和处理异步操作中的错误,使得错误处理更加直观。 - 调试方便:由于
async/await代码的结构更接近同步代码,调试时更容易跟踪代码的执行流程。
6. 注意事项
await只能在async函数内部使用,否则会抛出语法错误。async/await并不会改变 JavaScript 的单线程特性,它只是让异步代码的编写更加方便。- 在使用
async/await时,仍然需要注意避免阻塞主线程,特别是在处理大量异步操作时。