In my previous tutorial, we covered the basics of Promises in JavaScript. I said at the end of the article that promises allow us to run our code asynchronously.
In this tutorial, we will learn about the async
and await
keywords in JavaScript, which allow us to use Promises effectively and write cleaner asynchronous code.
async
FunctionLet’s start with asynchronous functions. Consider the following greeting function:
function greet() { return "Hello, World!"; } // Outputs: Hello, World! console.log(greet());
This is just a regular JavaScript function we've seen before. All it does is return a string that says "Hello, World!" However, we can turn this into an asynchronous function by just adding async
in front of it, like this:
async function greet() { return "Hello, World!"; } // Outputs: Promise { <state>: "fulfilled", <value>: "Hello, World!" } console.log(greet());
This time, the function returns a Promise
object with its state property set to Completed and its value set to Hello, World! In other words, the promise was resolved successfully.
We still return the string "Hello, World!" in the function definition. However, using the async
keyword means that the return value will be wrapped in a resolved Promise
object. The value of the resolved Promise will be the same as the value we returned from the async
function.
You can also return your own promise from an async
function like this:
async function greet() { return Promise.resolve("Hello, World!"); } // Outputs: Hello, World! greet().then((value) => console.log(value));
Basically, the async
keyword helps us define a function that always returns a promise. You can explicitly return a Promise yourself, or have the function wrap any return value that is not a Promise into a Promise.
await
KeywordsAny async
function can contain zero or more await
expressions. It is important to remember that the await
keyword is only valid inside an async
function. The await
keyword is used to wait for a Promise
to resolve or be rejected, and then get the completed value.
We use the await
keyword, the syntax is as follows:
await expression
The expression can be a native Promise
, in which case it is used directly and natively waited. In this case, there will be no implicit call to then()
. The expression can be a thenable object, in which case a new Promise
will be constructed by calling the then()
method. The expression can also be a non-thenable value. In this case, an already implemented Promise
will be constructed for us to use.
Suppose a promise has been fulfilled. async
The execution of the function will still be suspended until the next tick. It's important to remember this.
The following is an example of using the await
keyword in an async
function:
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));
Here is another example of using the await
keyword with an async
function when using Promise explicitly:
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));
This time, we explicitly use a Promise that resolves in 2 seconds. Therefore, the "Hello, World" greeting will be printed after two seconds.
We will now write two different greeting functions and see the order in which they output their results.
function n_greet(person) { return `Hello, ${person}!`; } async function a_greet(person) { let greeting = await `Hello, ${person}!`; return greeting; }
Our first function n_greet()
is a normal function that returns a string as output. Our second function is the async
function, which uses an expression after the await
keyword. The return value in this case is a fulfilled promise.
Here is the code snippet that calls all these functions and logs the output:
a_greet("Andrew").then((msg) => console.log(msg)); console.log(n_greet("Adam")); /* Output in order: Hello, Adam! Hello, Andrew! */
Greetings from Adam n_greet()
The function call has ended. However, he was first welcomed in output. This is because the function call returns a string directly.
a_greet()
The function call that greets Andrew at the beginning leads to the construction of a promise that has been fulfilled. However, execution remains suspended until the next clock cycle. That's why the output greeting appears after the greeting to Adam.
Now, we will define a slightly more complex async
function that contains multiple statements. One of these statements will have the await
keyword. You will see that using the await
keyword in an async
function pauses the execution of other statements following the await
statement.
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; }
Our async
function contains an explicitly defined Promise, preceded by the await
keyword. This means that the await
keyword will wait for the Promise to be fulfilled and then return the fulfilled value. The promise will take 2 seconds to materialize, so after about 2 seconds we should see "After Await..." in the console log.
This is a code snippet that will record some statements of our async
function:
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 的行为。
The above is the detailed content of Explore the power of async and wait in JavaScript. For more information, please follow other related articles on the PHP Chinese website!