ES8 集锦六:异步 - async /await
异步编程是前端开发中一个非常重要、不可避免的话题。相比于回调函数、Promise,ES8 中引入了 async /await,使得异步代码的编写更加简单、直观。本文将详细讲解使用 async /await 进行异步编程的技巧以及注意事项。
- async /await 是什么
async 函数是 ES8 中一个非常重要的新特性,其特点是返回一个 Promise 对象,在函数中可以使用 await 关键字来等待一个 Promise 对象的结果。下面是一个使用 async /await 实现的异步例子:
async function getData() { let result = await fetch('/data'); let data = await result.json(); return data; } getData() .then(data => console.log(data)) .catch(error => console.error(error));
在上面的例子中,getData
函数使用了 async 关键字来声明一个异步函数,其中使用了 await 关键字等待一个 Promise 对象(在这里是使用 fetch 来获取数据)。当 Promise 对象成功地 resolve 之后,使用 await 关键字得到 Promise 的返回结果,而不是使用回调函数或 Promise 的 then 方法来获取结果。
- async /await 的优缺点
与传统的回调函数和 Promise 相比,async /await 的优点在于:
- 代码更加清晰易读:使用 async /await 可以让异步代码的写法更加简洁、类似于同步代码;
- 错误处理更加方便:使用 try...catch 可以很方便地捕获异步函数中的错误,而不用写一堆的 catch 函数;
- 可以使用同步的方式编写异步代码:async 函数会返回一个 Promise 对象,一些异步操作可以像同步一样调用,使得代码更加简单清晰。
缺点在于:
- 删除了一些细节:async /await 抽象了一部分细节,例如:Promise 对象的状态、触发 resolve /reject 的时机等等,虽然使得编写代码更加方便,但也让一些底层的细节隐藏了起来;
- 另外,async /await 是 ES8 的新特性,浏览器对其的支持可能不够完善,具体可以参考该特性的浏览器支持情况表格。
- async /await 的防错技巧
与 Promise 相比,async /await 有一些自己的防错技巧。下面是一些常见的防错技巧:
- 对于可能抛出错误的代码,使用 try...catch 来捕获错误。例如:
async function getData() { try { let result = await fetch('/data'); let data = await result.json(); return data; } catch (error) { throw new Error(`Fetch数据失败:${error}`); } }
- 使用 Promise 的 catch 方法来捕获错误。例如:
getData() .then(data => console.log(data)) .catch(error => console.error(error));
在上面的代码中,当 getData
中发生错误时,会把该错误传递到 promise chain 的 catch 方法中进行处理。
- 如果在一个 async 函数中多次使用 await,应该将每个 await 中的 Promise 包裹在 try...catch 中,以便能定位到每个 await 时出现的错误。
async function login(username, password) { let response = await fetch('/login'); let token = await response.json(); try { let user = await getUserInfo(token.userId); return user; } catch (error) { throw new Error(`获取用户信息出错:${error}`); } } async function getUserInfo(userId) { let response = await fetch(`/user/${userId}`); return await response.json(); }
- async /await 示例代码
下面是一个使用 async /await 实现的多个异步请求例子:
async function getUsers() { let response = await fetch('/users'); let users = await response.json(); let promises = users.map(user => { return fetch(`/user/${user.id}`) .then(response => response.json()) .then(user => { return { id: user.id, name: user.name, email: user.email }; }); }); let result = await Promise.all(promises); return result; }
在上面的代码中,getUsers
函数会获取用户列表,然后根据每个用户的 id,发送一个独立的请求来获取每个用户的详细信息。使用 Promise.all 来等待所有请求返回结果。最终该函数会返回一个具有 id、name、email 属性的 user 列表。
总结
async /await 是 ES8 中的一个非常有用的异步编程特性,它可以使得异步代码更加简洁、易读,而且通过 try...catch 可以更方便地捕获错误。使用 async /await 进行异步编程时,需要注意取消细节,和一些异步编程的技巧。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a50e67add4f0e0ffd7799a