企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 章节导航 [TOC] #### Prerequisites ES 2017 introduced**Asynchronous**functions. Async functions are essentially a cleaner way to work with asynchronous code in JavaScript. In order to understand exactly what these are, and how they work, we first need to understand**Promises**. If you don’t know what Promises are, you should[**read this article I published on Promises**](https://codeburst.io/javascript-learn-promises-f1eaa00c5461)**before proceeding**.**You will not understand Async/Await in JavaScript until you understand Promises.** * * * #### What is Async/Await? * The newest way to write asynchronous code in JavaScript. * It is non blocking (just like promises and callbacks). * Async/Await was created to simplify the process of working with and writing chained promises. * 异步函数返回Promise。如果函数抛出错误,Promise将被拒绝。如果函数返回值,则将解析Promise。 #### Syntax Writing an async function is quite simple. You just need to add the`async`keyword prior to`function`: ~~~ // Normal Function ~~~ ~~~ function add(x,y){ return x + y; } ~~~ ~~~ // Async Function ~~~ ~~~ async function add(x,y){ return x + y; } ~~~ #### Await Async functions can make use of the`await`expression. This will pause the`async`function and wait for the Promise to resolve prior to moving on. #### Example Time Enough talk. To understand what all of this means, lets look at an example! First we’re going to create some code using promises. Once we’ve got something working, we’ll rewrite our function using async/await so you can see just how much simpler it is! > If you’re using Google Chrome, be sure to follow along by typing in the code into your developer console. You can open the console by pressing Ctrl+Shift+J (Windows / Linux) or Cmd+Opt+J (Mac). Consider the below code: ~~~ function doubleAfter2Seconds(x) { return new Promise(resolve => { setTimeout(() => { resolve(x * 2); }, 2000); }); } ~~~ In this code we have a function called`doubleAfter2Seconds`. This function will take a number as input and will resolve two seconds later with the number doubled. We can invoke our function and pass in the number 10 to try it out. To do this, we’ll call our function while passing in`10`. Then, after the promise has resolved, we’ll take our returned value and log it to the console. Here’s what this would look like: ~~~ doubleAfter2Seconds(10).then((r) => { console.log(r); }); ~~~ Awesome! But what if we want to run a few different values through our function and add the result? Unfortunately, we cant just add our invocations together and log them: ~~~ let sum = doubleAfter2Seconds(10) + doubleAfter2Seconds(20) + doubleAfter2Seconds(30); console.log(sum); ~~~ ~~~ // undefined ~~~ The problem with the above code is it doesn’t actually wait for our promises to resolve before logging to the console. One possible solution is to set up a promise chain. To do this we’ll create a new function called`addPromise`. Our function will take an input value, and will return a Promise. Here’s what the boilerplate code looks like: ~~~ function addPromise(x){ return new Promise(resolve => { ~~~ ~~~ // Code goes here... // resolve() ~~~ ~~~ }); } ~~~ Awesome. Now we can add in our calls to our`doubleAfter2Seconds`function. Once we’re done, we can resolve with our new sum. In this example we should be returning`x + 2*a + 2*b + 2*c`. Here’s the code: ~~~ function addPromise(x){ return new Promise(resolve => { doubleAfter2Seconds(10).then((a) => { doubleAfter2Seconds(20).then((b) => { doubleAfter2Seconds(30).then((c) => { resolve(x + a + b + c); }) }) }) }); } ~~~ Lets walk through the code again, line by line. * First, we create our function`addPromise`. This function accepts one parameter. * Next, we create our`new Promise`that we’ll be returning. Note that for the sake of simplicity, we’re not handling rejections/errors. * Next we invoke`doubleAfter2Seconds`for the first time, passing in a value of`10`. Two seconds later, the return value of`20`will be returned to the`a`variable. * We invoke`doubleAfter2Seconds`again, this time passing in a value of`20`. Two seconds later, the return value of`40`will be returned to the`b`variable. * We invoke`doubleAfter2Seconds`one final time, this time passing in a value of`30`. Two seconds later, the return value of`60`will be returned to the`c`variable. * Finally, we resolve our Promise with the value of`10 + 20 + 40 + 60`or`130`. When we put all of the code together, here’s what it looks like: ``` function twoSeconds(x){ return new Promise(resolve =>{ setTimeout(() => { resolve(x*2); },2000); }); } function addPromise(x){ return new Promise(resolve =>{ twoSeconds(10).then((a) => { twoSeconds(20).then((b) =>{ twoSeconds(30).then((c) =>{ resolve(x + a +b + c) }) }) }) }) } ``` #### Switching from Promises to Async/Await. Awesome! Now lets see just how much easier we could write the above code with Async/Await! Remove the`addPromise`function, and create a new function named`addAsync`. This function will have the exact same purpose as our`addPromise`did. When you create your`addPromise`function, make use of the`async`keyword. Here’s what that looks like: ~~~ async function addAsync(x) { ~~~ ~~~ // code here... ~~~ ~~~ } ~~~ Now that you’ve created an async function, we can make use of the`await`keyword which will pause our code until the Promise has resolved. Here’s how easy that is: ~~~ async function addAsync(x) { const a = await doubleAfter2Seconds(10); const b = await doubleAfter2Seconds(20); const c = await doubleAfter2Seconds(30); return x + a + b + c; } ~~~ And here’s the full code: ``` function doubleAfter2Seconds(x) { return new Promise (resolve => { setTimeout(() => { resolve(x \* 2); },2000); }); } async function addAsync(x){ const a = await doubleAfter2Seconds(10); const b = await doubleAfter2Seconds(20); const c = await doubleAfter2Seconds(30); return x + a + b + c; } addAsync(10).then((sum) =>{ console.log(sum); }) ``` As you can see, we’re still making use of the same`doubleAfter2Seconds`function. Similarly, we’ll be invoking our`addAsync()`function and passing in the value of`10`. Upon completion, we log the resulting value. Let’s walk through this step-by-step: * First we call`addAsync(10)`passing in the value of`10`. * Next, we get the value of`a`on line 10. Since the`await`keyword is used, our function pauses for two seconds while we wait for the promise to resolve. Once the promise resolves,`a = 20`. ~~~ const a = await ~~~ * Next, we get the value of`b`on line 11. Since the`await`keyword is used, our function pauses for two seconds while we wait for the promise to resolve. Once the promise resolves,`b = 40`. ~~~ const b = await ~~~ * Next, we get the value of`c`on line 12. Since the`await`keyword is used, our function pauses for two seconds while we wait for the promise to resolve. Once the promise resolves,`c = 60`. ~~~ const c = await ~~~ * Finally, we can return the value of`x + a + b + c`. Since we passed in`10`as our single parameter, we are returning the value of`10 + 20 + 40 + 60`. * A full six seconds later, our`console.log(sum)`is finally run. The value of`10 + 20 + 40 + 60`is passed in, and`130`is logged to the console. And that’s it! You’ve just created an asynchronous function in JavaScript! **As you can see, since Async functions return a Promise, they can be used interchangeably with Promises very easily. Our code is also so much cleaner and easier to read when we use Async/Await instead of long Promise chain.** * * * ### Closing Notes: Thanks for reading, and hopefully this was helpful. There is much more to Async/Await — including error handling — that we didn’t cover in this article. ### If you’re still having trouble understanding what Async/Await is, it’s probably because you don’t fully understand how Promises work. Promises are key to understanding this topic. Additional information can be found on Promises[here](https://developers.google.com/web/fundamentals/primers/promises),[here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), and[here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises).