在我之前的教程中,我们介绍了 JavaScript 中 Promise 的基础知识。我在文章的最后说,promise 允许我们异步运行我们的代码。
在本教程中,我们将学习 JavaScript 中的 async
和 await
关键字,它们使我们能够有效地使用 Promise 并编写更简洁的异步代码。
定义 async
函数
让我们从异步函数开始讨论。考虑以下问候语函数:
function greet() { return "Hello, World!"; } // Outputs: Hello, World! console.log(greet());
这只是我们之前见过的常规 JavaScript 函数。它所做的只是返回一个字符串,上面写着“Hello, World!”不过,我们可以将其变成异步函数,只需在其前面添加 async
即可,如下所示:
async function greet() { return "Hello, World!"; } // Outputs: Promise { <state>: "fulfilled", <value>: "Hello, World!" } console.log(greet());
这一次,该函数返回一个 Promise
对象,其 state 属性设置为已完成,值设置为 Hello, World! 换句话说,promise 已成功解析。
我们仍然返回字符串“Hello, World!”在函数定义里面。但是,使用 async
关键字意味着返回值将包装在已解析的 Promise
对象中。已解决的 Promise 的值将与我们从 async
函数返回的值相同。
您还可以从 async
函数返回您自己的承诺,如下所示:
async function greet() { return Promise.resolve("Hello, World!"); } // Outputs: Hello, World! greet().then((value) => console.log(value));
基本上,async
关键字帮助我们定义始终返回承诺的函数。您可以自己显式返回一个 Promise,也可以让函数将任何不是 Promise 的返回值包装到 Promise 中。
await
关键字
任何 async
函数都可以包含零个或多个 await
表达式。重要的是要记住 await
关键字仅在 async
函数内有效。 await
关键字用于等待 Promise
解析或拒绝,然后获取已完成的值。
我们使用 await
关键字,语法如下:
await expression
表达式可以是原生的Promise
,这种情况下直接使用,原生等待。在这种情况下,不会有对 then()
的隐式调用。表达式可以是 thenable 对象,在这种情况下,将通过调用 then()
方法构造一个新的 Promise
。该表达式也可以是不可thenable 的值。在这种情况下,将构建一个已经实现的 Promise
供我们使用。
假设一个承诺已经兑现了。 async
函数的执行仍然会暂停,直到下一个tick。记住这一点很重要。
以下是在 async
函数中使用 await
关键字的示例:
async function greet() { let greeting = await "Hello, World!"; return greeting; } // Outputs: [Function: Promise] console.log(greet().constructor); // Outputs: Hello, World! greet().then((msg) => console.log(msg));
这是在显式使用 Promise 时将 await
关键字与 async
函数结合使用的另一个示例:
async function greet() { let greeting = new Promise((resolve) => { setTimeout(() => { resolve("Hello, World!"); }, 2000); }); return greeting; } // Outputs: [Function: Promise] console.log(greet().constructor); // Outputs: Hello, World! greet().then((msg) => console.log(msg));
这一次,我们明确使用了一个在 2 秒内解析的 Promise。因此,“Hello, World”问候语将在两秒后打印。
了解语句的执行顺序
我们现在将编写两个不同的问候函数并查看它们输出结果的顺序。
function n_greet(person) { return `Hello, ${person}!`; } async function a_greet(person) { let greeting = await `Hello, ${person}!`; return greeting; }
我们的第一个函数 n_greet()
是一个返回字符串作为输出的普通函数。我们的第二个函数是 async
函数,它在 await
关键字之后使用表达式。本例中的返回值是一个已经履行的承诺。
这是调用所有这些函数并记录输出的代码片段:
a_greet("Andrew").then((msg) => console.log(msg)); console.log(n_greet("Adam")); /* Output in order: Hello, Adam! Hello, Andrew! */
问候 Adam 的 n_greet()
函数调用已结束。然而,他在输出中首先受到欢迎。这是因为函数调用直接返回一个字符串。
a_greet()
函数调用是在开始时向 Andrew 打招呼的,它导致了一个已经履行的承诺的构建。然而,执行仍然暂停,直到下一个时钟周期。这就是为什么输出问候语出现在对 Adam 的问候语之后。
现在,我们将定义一个稍微复杂一点的 async
函数,其中包含多个语句。这些语句之一将具有 await
关键字。您将看到,在 async
函数中使用 await
关键字会暂停执行 await
语句之后的其他语句。
function timeout(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } async function aa_greet(person) { console.log("Before Await..."); await timeout(2000); let greeting = `Hello, ${person}!`; console.log("After Await..."); return greeting; }
我们的 async
函数包含一个显式定义的 Promise,前面带有 await
关键字。这意味着 await
关键字将等待 Promise 被履行,然后返回已履行的值。该承诺将需要 2 秒才能实现,因此大约 2 秒后我们应该在控制台日志中看到“After Await...”。
这是代码片段,它将记录我们的 async
函数的一些语句:
console.log("Before Greeting Function..."); aa_greet("Monty").then((msg) => console.log(msg)); console.log("After Greeting Function..."); /* Output in Order 23:42:15.327 Before Greeting Function... 23:42:15.331 Before Await... 23:42:15.331 After Greeting Function... 23:42:17.333 After Await... 23:42:17.333 Hello, Monty! */
首先记录字符串“Before Greeting Function...”,因为这是我们进行的第一次调用。之后,我们调用 aa_greet()
函数。这会导致输出字符串“Before Await...”。然后,浏览器遇到 await
关键字。所以它等待承诺解决。与此同时,aa_greet()
函数之外的代码继续执行。这就是为什么我们在下一个日志条目中得到“After Greeting Function...”字符串作为输出。
一旦承诺得到解决,浏览器就会继续执行,我们会得到“After Await...”作为输出。最后,我们解析的问候语作为承诺返回,因为我们使用 async
函数。我们对这个已解决的 Promise 调用 then()
方法并记录“Hello, Monty!”到控制台。
通过 Fetch API 使用 async
和 await
await 关键字的一个常见用例是从远程 API 获取数据。这允许比嵌套回调或承诺链更干净的代码。
async function getData() { // use the fetch API to fetch data from an API endpoint const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); // check if the response is okay (HTTP status code 200-299) if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } // parse the response as JSON const data = await response.json(); return data; }
在此函数中,首先我们等待对 API 查询的初始响应。如果响应正常,我们就会等待 JSON 格式的完整响应数据。我们返回 JSON 数据,但请记住,由于这是一个异步函数,因此我们实际上返回一个最终解析为该数据的 Promise。因此,如果您想访问结果数据,您必须再次使用类似await关键字的东西!
const data = await getData();
最终想法
在上一篇教程中了解了 Promise
对象后,我们在本教程中讨论了 async
函数和 await
关键字。您现在应该能够编写自己的 async
函数,使用 await
关键字来使用更清晰、更易读的代码实现基于 Promise 的行为。
以上就是探索 JavaScript 中 async 和 wait 的威力的详细内容,更多请关注编程之家其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。