掌握JavaScript异步操作:Async/Await详解
本文深入探讨JavaScript中的async
/await
,教你如何高效掌控异步操作,编写更清晰易读的代码。
核心要点:
async
/await
简化了异步操作的处理,使代码看起来像同步执行,但实际上仍然是非阻塞的。async
函数返回一个Promise,await
关键字暂停函数执行,直到Promise解决,从而增强代码的可读性和流程控制。async
函数的错误处理可以使用try
/catch
块或Promise
的catch()
方法高效管理。Promise.all
可以优化并行运行异步命令,允许多个Promise
同时解决,而不是顺序执行。for...of
循环允许在循环中正确处理async
函数,确保正确的执行顺序和更好的性能管理。await
允许在ES模块的顶层使用await
,简化了异步代码的集成,无需额外的包装器。内容概要:
async
关键字await
关键字await
/async
底层使用Promiseasync
/await
catch()
方法await
await
在JavaScript中,一些操作是异步的。这意味着它们产生的结果或值不会立即可用。
考虑以下代码:
function fetchDataFromApi() { // 数据获取逻辑 console.log(data); } fetchDataFromApi(); console.log('数据获取完成');
JavaScript解释器不会等待异步fetchDataFromApi
函数完成,然后才执行下一条语句。因此,它会在记录API返回的实际数据之前记录数据获取完成
。
在许多情况下,这不是预期的行为。幸运的是,我们可以使用async
和await
关键字来使我们的程序等待异步操作完成,然后再继续执行。
此功能在ES2017中引入JavaScript,并受所有现代浏览器支持。
如何创建JavaScript异步函数
让我们仔细看看fetchDataFromApi
函数中的数据获取逻辑。JavaScript中的数据获取是异步操作的一个主要示例。
使用Fetch API,我们可以这样做:
function fetchDataFromApi() { // 数据获取逻辑 console.log(data); } fetchDataFromApi(); console.log('数据获取完成');
这里,我们从JokeAPI获取一个编程笑话。API的响应采用JSON格式,因此在请求完成后(使用json()
方法)我们提取该响应,然后将笑话记录到控制台。
请注意,JokeAPI是一个第三方API,因此我们无法保证返回的笑话质量!
如果我们在浏览器或Node(使用--experimental-fetch
标志的17.5 版本)中运行此代码,我们会看到控制台仍然以错误的顺序记录内容。
让我们改变一下。
async
关键字我们需要做的第一件事是将包含函数标记为异步函数。我们可以使用async
关键字来实现这一点,我们将它放在function
关键字的前面:
function fetchDataFromApi() { fetch('https://v2.jokeapi.dev/joke/Programming?type=single') .then(res => res.json()) .then(json => console.log(json.joke)); } fetchDataFromApi(); console.log('数据获取完成');
异步函数始终返回一个Promise(稍后详细介绍),因此只需将then()
链接到函数调用即可获得正确的执行顺序:
async function fetchDataFromApi() { fetch('https://v2.jokeapi.dev/joke/Programming?type=single') .then(res => res.json()) .then(json => console.log(json.joke)); }
如果我们现在运行代码,我们会看到类似这样的内容:
fetchDataFromApi() .then(() => { console.log('数据获取完成'); });
但我们不想这样做!JavaScript的Promise语法可能会有点复杂,这就是async
/await
闪光的地方:它使我们能够使用看起来更像同步代码的语法来编写异步代码,并且更易于阅读。
await
关键字接下来要做的是在函数中任何异步操作的前面加上await
关键字。这将强制JavaScript解释器“暂停”执行并等待结果。我们可以将这些操作的结果分配给变量:
<code>程序员的浪漫:一行代码解决千行代码的bug。 数据获取完成</code>
我们还需要等待调用fetchDataFromApi
函数的结果:
async function fetchDataFromApi() { const res = await fetch('https://v2.jokeapi.dev/joke/Programming?type=single'); const json = await res.json(); console.log(json.joke); }
不幸的是,如果我们现在尝试运行代码,我们会遇到一个错误:
await fetchDataFromApi(); console.log('数据获取完成');
这是因为我们不能在非模块脚本的async
函数之外使用await
。我们稍后将更详细地介绍这一点,但现在解决这个问题最简单的方法是用它自己的函数包装调用代码,我们也将其标记为async
:
<code>Uncaught SyntaxError: await is only valid in async functions, async generators and modules</code>
如果我们现在运行代码,所有内容都应该按正确的顺序输出:
async function fetchDataFromApi() { const res = await fetch('https://v2.jokeapi.dev/joke/Programming?type=single'); const json = await res.json(); console.log(json.joke); } async function init() { await fetchDataFromApi(); console.log('数据获取完成'); } init();
我们需要这个额外的样板代码这一事实是不幸的,但在我看来,代码仍然比基于Promise的版本更容易阅读。
前面的示例使用了两个命名函数声明(function
关键字后跟函数名),但我们并不局限于此。我们还可以将函数表达式、箭头函数和匿名函数标记为async
。
如果您想回顾一下函数声明和函数表达式之间的区别,请查看我们的指南
(后续内容同理,根据原文逐段改写,保持原意,并调整语言风格,使之更流畅自然)
以上是初学者的JavaScript异步指南,等待示例的详细内容。更多信息请关注PHP中文网其他相关文章!