在我之前的教學中,我們介紹了 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!”到控制台。
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 的威力的詳細內容。更多資訊請關注PHP中文網其他相關文章!