随着前端应用的复杂性不断增加,异步编程成为了必备技能。ES6 中引入的 Promise 对象大大简化了异步编程,但是仍然存在一些问题,例如嵌套过深、错误处理困难等。ES8 中引入的 async/await 机制则进一步简化了异步编程,使得代码更加清晰、易于维护。本文将介绍 ES12 中的 async 函数的应用及常见错误。
async 函数的基本用法
async 函数是一个返回 Promise 对象的异步函数,可以使用 await 关键字等待 Promise 对象的状态变化。下面是一个简单的例子:
async function foo() { console.log('start'); await new Promise(resolve => setTimeout(resolve, 1000)); console.log('end'); } foo();
输出结果为:
start (1 秒后) end
可以看到,async 函数的执行过程中,遇到 await 关键字时会暂停执行,等待 Promise 对象的状态变为 resolved 后再继续执行。async 函数也可以返回值,返回值会被包装成 Promise 对象:
async function bar() { return 42; } bar().then(console.log); // 输出 42
async 函数的错误处理
async 函数中的错误处理比较特殊。如果在 async 函数中抛出异常,会导致 Promise 对象的状态变为 rejected。可以使用 try/catch 语句捕获异常:
// javascriptcn.com 代码示例 async function baz() { try { await Promise.reject('error'); } catch (err) { console.log(err); } } baz(); // 输出 error
需要注意的是,如果 async 函数中没有显式处理异常,那么异常会被包装成一个 rejected 状态的 Promise 对象,需要使用 catch 方法捕获:
async function qux() { await Promise.reject('error'); } qux().catch(console.log); // 输出 error
async 函数的应用
1. 串行执行异步任务
在异步编程中,经常需要按照一定的顺序执行异步任务。ES6 中可以使用 Promise 的链式调用来实现,但是比较繁琐。使用 async/await 可以更加清晰地表达代码的逻辑。下面是一个例子,按照顺序执行三个异步任务:
// javascriptcn.com 代码示例 async function task1() { await new Promise(resolve => setTimeout(resolve, 1000)); console.log('task1'); } async function task2() { await new Promise(resolve => setTimeout(resolve, 500)); console.log('task2'); } async function task3() { await new Promise(resolve => setTimeout(resolve, 2000)); console.log('task3'); } async function main() { await task1(); await task2(); await task3(); } main();
输出结果为:
(1 秒后) task1 (0.5 秒后) task2 (2 秒后) task3
可以看到,使用 async/await 可以非常清晰地表达代码的执行顺序。
2. 并行执行异步任务
在某些情况下,需要同时执行多个异步任务,等待它们全部完成后再进行下一步操作。可以使用 Promise.all 方法和 async/await 结合来实现。下面是一个例子:
// javascriptcn.com 代码示例 async function task4() { await new Promise(resolve => setTimeout(resolve, 1000)); console.log('task4'); return 4; } async function task5() { await new Promise(resolve => setTimeout(resolve, 500)); console.log('task5'); return 5; } async function task6() { await new Promise(resolve => setTimeout(resolve, 2000)); console.log('task6'); return 6; } async function main2() { const [result4, result5, result6] = await Promise.all([task4(), task5(), task6()]); console.log(result4, result5, result6); } main2();
输出结果为:
(2 秒后) task6 (1 秒后) task4 (0.5 秒后) task5 4 5 6
可以看到,使用 Promise.all 方法和 async/await 结合可以非常方便地实现并行执行异步任务。
async 函数的常见错误
1. 忘记使用 await
在 async 函数中,如果忘记使用 await 关键字等待 Promise 对象的状态变化,会导致代码的执行顺序出现问题。例如:
async function error1() { console.log('start'); new Promise(resolve => setTimeout(resolve, 1000)); console.log('end'); } error1(); // 输出 start end (1 秒后)
在这个例子中,Promise 对象的状态变化不会影响代码的执行顺序,因此输出结果不符合预期。
2. 没有正确处理异常
在 async 函数中,如果没有正确处理异常,会导致代码无法正常执行。例如:
async function error2() { await Promise.reject('error'); } error2(); // Uncaught (in promise) error
在这个例子中,没有使用 catch 方法捕获异常,因此会导致代码抛出异常并中断执行。
总结
async 函数是 ES12 中非常有用的异步编程机制,可以使代码更加清晰、易于维护。在使用 async 函数时,需要注意正确处理异常,避免常见错误。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6572fac1d2f5e1655dc12fc9