compatibility
To remind you, Node now supports async/await from version 7.6. And just a few days ago, Node 8 has been officially released and you can use it with confidence.
If you haven't tried it yet, here's a bunch of examples of reasons why you should take it right away and never look back.
async/await
For those who have never heard of this topic, here is a simple introduction:
Async/await is a new way of writing asynchronous code. The scenarios for the previous async code are callbacks and promise.
Async/await is actually built on the basis of promise. It cannot be used with normal callbacks or node callbacks.
Async/await, like promise, is also non-blocking.
Async/await makes asynchronous code look and behave more like synchronous code. This is where its power lies.
Grammar
Suppose the function getJSON
returns one promise
, and the promise
completion value is some JSON object. We just want to call it and output the JSON, and then return "done"
.
Here is the code implemented with promise:
Const MAKEREQUEST = () = Getjson () = { console.log (data) return "Done" }) makerequest ()
And that's what it async/await
looks like:
Const MAKEREQUEST = Async () = { Console.log (await Getjson ()) return "Done" c20/>} makerequest ()
Here are some differences:
There is a keyword in front of the function async
. await
keywords are used only async
within defined functions. All async
functions implicitly return a promise, and promise's completion value will be the return value of the function (in this case "done"
).
The above point implies that we cannot use the top level of the code await
, because it is not async
within the function.
// This code cannot be executed at the top level // await MakeRequest () // This code can be executed = = {// do something})
3. await getJSON()
means that the console.log
call waits until getJSON()
promise finishes and prints out its value.
Why async/await better? 1. Simple and clean
See how much code we write less! Even in the man-made example above, it is clear that we are saving a lot of code. We do not have to write .then
, create an anonymous function to handle the response, or give a name to a variable that is not needed data
. We also avoided code nesting. These small advantages can accumulate quickly and become more pronounced in the subsequent code.
2. Error handling
Async/await will eventually allow us to use the same structure ( try/catch
) to process synchronous and asynchronous code into possibilities. In the example below using promise, if it fails, it will JSON.parse
try/catch
not be processed because it occurs in a prmoise. We need to raise the promise and .catch
repeat the error handling code. This error-handling code is more complex than the code that can be used in production console.log
.
Const MAKEREQUEST = () = { Try{Getjson (). Then (Result= { //This parse may failConst DATA =json.parse (Result) console.log (data)}) //uncomment this block to handle asynchronous errors //. catch (Err) = { //Console.log (Err) // }) }Catch(Err) {Console.log (Err)}}
Now look at the code implemented with async/await. Now the catch
block will handle parsing errors.
Const MAKEREQUEST = Async () = { try// This parse will fail const DATA = Json.parse (await Getjson ()) Console.log (data) } catch (err) { Console.log (err ) }}
3. Conditional sentences
Suppose you want to do something like the following code, get some data, decide whether you should return the data, or get more details based on some of the values in the data.
Const MAKEREQUEST = () = { return Getjson () = { if (data.needsanotherrequest) { return makeanotherrequest (data) = { Console.log (moredata) return moredata }) Else { console.log (data) return data }} ) }
This code looks a headache to people. It simply propagates the final results to the main promise, but it's easy to get lost in nesting (6 layers), curly braces, and return statements.
Rewrite This example with async/await, and it becomes easier to read.
Const MAKEREQUEST = Async () = { = await Getjson () if ( Data.needsanotherrequest) { = await makeanotherrequest (data); Console.log (moredata) return moredata Else { Console.log (data) return data } }
4. Median value
You may find yourself in a state where you call your promise1, then use its return value to invoke Promise2, and then use the results of these two promise to invoke PROMISE3. Your code is likely to look like this:
Const MAKEREQUEST = () = { return promise1 () = { // Do something return Promise2 (value1) = = {// do something return promise3 (value1, value2)})} ) }
If you promise3
don't need it value1
, it's easy to flatten the promise nesting. If you're the kind of person you can't stand, you might like the following, Promise.all
containing values 1 and 2 in one, and avoiding deeper nesting:
Const MAKEREQUEST = () = { return promise1 () = { // Do something return Promise.all ([Value1, Promise2 (value1)]) }) = = {// do something return promise3 (value1, value2)} ) }
This method sacrifices semantics for readability. In addition to avoiding promise nesting, there is no reason to combine value1
and value2
incorporate an array.
But with async/await, the same logic becomes super simple and intuitive. This will make you wonder about all the things you've done to make promise look less scary.
Const MAKEREQUEST = Async () = { = await promise1 () = await Promise2 (value1) return promise3 (value1, value2) }
5. Error stack
If there is a chain of code that calls multiple promise, an error is thrown somewhere in the chain.
Const MAKEREQUEST = () = { returncallapromise (). Then (()=callapromise ()). Then (()=callapromise ()). Then (()=callapromise ()). Then (()=callapromise ()). Then (()= { Throw NewError ("oops"); })} makerequest ().Catch(Err ={console.log (err); //Output //error:oops at CallAPromise.then.then.then.then.then (index.js:8:13)})
The error stack returned from the promise chain did not find clues as to where the error occurred. Worse, this is misleading; the only function name it contains is callAPromise
that it is completely unrelated to this error (although the file and line numbers are still useful).
However, the error stack from async/await points to the function that contains the error:
Const MAKEREQUEST = Async () = { await callapromise () await callapromise () await callapromise () await callapromise () await callapromise () thrownew Error ("oops"); } MakeRequest () . Catch (err = { console.log (err); // Output // error:oops at MakeRequest (index.js:7:9) })
This is not a big deal when developing in the local environment and opening files in the editor, but it is useful when you want to figure out the error log from the production server. In this case, it is better to know that the error occurred in the makeRequest
middle than to know the error from one another then
.
6. Commissioning
Last but not least, when using async/await, a killer advantage is that debugging is easier. Debugging promise has been so painful for two reasons:
You cannot set breakpoints in an arrow function that returns an expression (no function body).
Const MAKEREQUEST = Async () ={ await callapromise () await callapromise () await callapromise () await callapromise () //Try set a breakpoint here await callapromise ()}
2. If you .then
set a breakpoint in a block and use a debug shortcut like one step debugging, the debugger does not move to the back .then
because it only steps through the synchronization code.
With async/await, we don't need so many arrow functions, you can step through the await call just as you would a normal synchronous call.
Summary
Async/await is one of the most revolutionary features added to JavaScript in the last few years. It gives us a sense of how chaotic the promise syntax is and provides an intuitive alternative.
concern
You may have some legitimate doubts about using this feature:
It makes asynchronous code less obvious: Our eyes have learned that it takes a few weeks to adapt to the new flag as long as you see the callback or .then
recognize the async code.
Don't worry about Node7 non-LTS version support, because node 8 is now out and will be the next LTS version, and migrating our codebase to the new version is likely to be effortless.
Recommended
Here is an article on Cnode Introducing async/await:http://cnodejs.org/topic/5640b80d3a6aa72c5e0030b6
JavaScript Asynchronous Programming--async/await vs Promise