What is async?

Please leave a comment for discussion.

The async function is the syntax sugar for Generator functions. Use the keyword async to indicate asynchrony, and use await inside the function to indicate asynchrony. Compared to Generator, async functions improve in the following four aspects:

  • Built-in actuator. Generator functions must rely on an actuator for execution, whereas async functions come with an actuator and are called in the same way as normal functions

  • Better semantics. Async and await are more semantic than * and yield

  • Wider applicability. The co module convention is that the yield command can only be followed by the Thunk function or Promise object. The async function’s await command, on the other hand, can be followed by a Promise or a primitive value (Number, string, Boolean, but this is equivalent to synchronous operations).

  • The return value is Promise. The async function returns a Promise object, which is more convenient than the Iterator returned by the Generator function and can be called directly using the then() method

Understand async/await

Async is a new feature in ES7 that indicates that the current function is asynchronous and does not block the thread causing subsequent code to stop running.

How to use

Once declared, the call can be made

Async function asyncFn() {return 'hello world'; } asyncFn();Copy the code

So that means that this is an asynchronous function, and that’s what it returns

     

Async means that there are asynchronous operations in the function
Await means that the following expression needs to wait for the result.

Return a Promise object in the resolved state with the value of return. So let’s look at this function down here

Async function asyncFn() {return 'asyncFn'} asyncFn().then(result => {console.log(result); }) console.log(' I execute first ');Copy the code

AsyncFn () is defined as an asyncFn() function, but the asyncFn() function is defined as an asyncFn() function.

Now that you understand the basic use of async, what other features do you have?

Async-defined functions internally return a promise object by default. If the function throws an exception or returns Reject, the promise state is rejected.

async function e() { throw new Error('has Error'); } e().then(success => console.log(' success ', success)).catch(error => console.log(' failure ', error));Copy the code

We see that an exception is thrown inside the function, reject is returned, the async function receives it, determines that the execution failed and enters a catch. The error is printed.

Async function throwStatus() {return 'throwStatus'} throwStatus().then(success => console.log(' success ', Success)).catch(error => console.log(' failed ', error)); // Print the result successfully to return all types of valuesCopy the code

The async function receives a value, reject or reject, and determines that it is reject. The async function can return a value of any data type, such as false,NaN,undefined… Resolve

The async function rejects the reject response

  1. Contains variables or functions that are directly used and not declared.

  2. Throw new Error or return the reject state return promise.reject (‘ Failed to execute ‘)

  3. Function method execution error (🌰 : Object uses push()) etc…

Also, in async, you have to return the result, otherwise either reject or resolved will be undefine. It is recommended to use the arrow function.

The rest of the return results are determined that resolved executed successfully.

// Reject correctly. The reject state must be returned out. async function PromiseError() { return Promise.reject('has Promise Error'); Async function PromiseError() {promise.reject (' this is the wrong way to do it '); } PromiseError().then(success => console.log(' success ', success)).catch(error => console.log(' failure ', error));Copy the code

We see a Promise object printed in the second line. Don’t worry, this is the default behavior in the Chrome console, and this is what we normally do when we assign values in the console. If the statement or expression does not return a value, the default value is undefined.

var a = 1; //undefined ------------------------------------------------------------ console.log(a); //1 //undefined ------------------------------------------------------------ function a(){ console.log(1) } a(); //1 //undefined ------------------------------------------------------------ function b(){ return console.log(1) } b(); //1 //undefined ------------------------------------------------------------ function c(){ return 1} c(); / / 1 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- async function d () {} 'this value to receive less than' d (). Then (success = > The console. The log (' success, success)); //Promise {<resolved>: Undefined} -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- async function e () {return} 'received' E ().then(success => console.log(' success ',success)); //Promise {<resolved>: undefined}Copy the code

The last line Promise {

: undefined} is returned because the console.log execution statement does not return a value.

D ().then(function(success){return console.log(' success ',success); });Copy the code

Js itself is single threaded, with V8 we can have the ability to be “asynchronous”

Now that we know async, let’s talk about await.

What is await?

Await means async wait. This keyword can only be used in functions defined with async. Any async function will return a promise by default, and the value resolved by the promise will be the return value of the function. Async must wait until all internal promise objects of the await command have been executed before the state changes.

For example, await is a student and async is a school bus that must wait for everyone to drive.

That is, we must wait until all the ‘await’ functions have completed before we tell the ‘promise’ whether I succeeded or failed, and then or catch
async function awaitReturn() { return await 1 }; AwaitReturn ().then(success => console.log(' success ', success)).catch(error => console.log(' failure ',error))Copy the code

In this function, there is an await function. Async will wait until the await 1 step is complete before returning the promise state, which is determined, without a doubt, as resolved.

A lot of people thinkawaitIt waits for the next expression to execute before continuing with the next code,In factawaitIs a sign to yield a thread.awaitSubsequent functions are executed once (such as await Fn() ‘s Fn, not the next line of code), and then the whole thing jumps outasyncFunction to execute the following js stack code. When this round of events completes, it jumps back toasyncReturn value of the expression after await**** in the function, if the return value is notpromiseThen continue to executeasyncFunction, otherwise it will returnpromiseIn thePromiseJob Queue (Promise Job Queue)

Let’s do a simpler example

const timeoutFn = function(timeout){ return new Promise(function(resolve){ return setTimeout(resolve, timeout); }); } async function fn(){ await timeoutFn(1000); await timeoutFn(2000); Return 'complete '; } fn().then(success => console.log(success));Copy the code

This could have been written more easily as an arrow function, but for the sake of reading the essence, instead of ES5, all await functions in the above execution function will return the state, resulting in 3 seconds after the execution ‘completed’.

Normally, the await command is followed by a Promise, and if not, it is converted to an immediately resolved Promise.

Or you could write it this way

function timeout(time){ return new Promise(function(resolve){ return setTimeout(function(){ return resolve(time + 200) },time); })} function first(time){console.log(' first delay '+ time); return timeout(time); } function second(time){console.log(' second delay '+ time); return timeout(time); } function third(time){console.log(' third delay '+ time); return timeout(time); } function start(){ console.log('START'); const time1 = 500; First (time1).then(time2 => second(time2)).then(time3 => third(time3)).then(res => {console.log(' last delay '+ res); console.timeEnd('END'); })}; start();Copy the code

Resolve is thus executed using a THEN chained callback

The first delay is 500. The second delay is 700. The third delay is 900. The last delay is 1100Copy the code

Using async/await?

async function start() { console.log('START'); const time1 = 500; const time2 = await first(time1); const time3 = await second(time2); const res = await third(time3); Console. log(' last delay ${res} '); console.log('END'); } start();Copy the code

The same effect was achieved. There is a problem with this, however, if the await execution encounters an error

async function start() { console.log('START'); const time1 = 500; const time2 = await first(time1); const time3 = await Promise.reject(time2); const res = await third(time3); Console. log(' last delay ${res} '); console.log('END'); } start();Copy the code

Reject, reject, reject, reject, reject, reject, reject, reject, reject, reject, reject

let last; async function throwError() { await Promise.reject('error'); Last = await '; } throwError().then(success => console.log(' success ',last)).catch(error => console.log(' failure ',last)).catch(error => console.log(' failure ',last))Copy the code

`
Actually,`

Async functions are not difficult, but error handling is difficult.

The above function, after the execution of the await has excluded an error, stops the further execution, resulting in an error reporting no last assignment.

If async has multiple await functions and any of them throws an exception or an error, the function is rejected.

So how do you do that? You can do a try/catch, and when you encounter a function, you can throw the error and just keep going.

let last; async function throwError() { try{ await Promise.reject('error'); Last = await '; }catch(error){ console.log('has Error stop'); }} throwError().then(success => console.log(' success ',last)).catch(error => console.log(' failure ',last)).catch(error => console.log(' failure ',last))Copy the code

In this case, you can proceed with the execution.

Practice with 🌰

function testSometing() { console.log("testSomething"); return "return testSomething"; } async function testAsync() { console.log("testAsync"); return Promise.resolve("hello async"); } async function test() { console.log("test start..." ); const testFn1 = await testSometing(); console.log(testFn1); const testFn2 = await testAsync(); console.log(testFn2); console.log('test end... '); } test(); var promiseFn = new Promise((resolve)=> { console.log("promise START..." ); resolve("promise RESOLVE"); }); promiseFn.then((val)=> console.log(val)); console.log("===END===")Copy the code

The execution result

Let’s break it down step by step

Test () prints test start…

Then testFn1 = await testSomething(); The testSometing() function is first executed to print out the string “testSometing”.

TestAsync () returns resolve, after which the await will give the thread the ability to execute, triggering promiseFn to print “Promise START…” .

Next, put the returned Promiseresolve(” Promise RESOLVE”) into the Promise Queue (the promise Job Queue) and continue printing “=== =END===”.

At the end of the loop, it jumps back into the async function (test()) and waits for the return value of the expression following the await. Since testSometing() is not an async function, it returns a string “return testSometing”.

Then ((val)=> console.log(val)); then((val)=> console.log(val)); Print “Promise RESOLVE.”

Then, as before, we jump back to test and continue with the return value of console.log(testFn2), printing “Hello Async”.

Finally print “Test end…” .

Make testSomething() async

async function testSometing() { console.log("testSomething"); return "return testSomething"; } async function testAsync() { console.log("testAsync"); return Promise.resolve("hello async"); } async function test() { console.log("test start..." ); const testFn1 = await testSometing(); console.log(testFn1); const testFn2 = await testAsync(); console.log(testFn2); console.log('test end... '); } test(); var promiseFn = new Promise((resolve)=> { console.log("promise START..." ); resolve("promise RESOLVE"); }); promiseFn.then((val)=> console.log(val)); console.log("===END===")Copy the code

The execution result

Then ((val)=> console.log(val)); Precedes console.log(testFn1).

The reason is that the current version of async functions will be await resolve,

function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}
console.log(Object.prototype.toString.call(testSometing)) // [object Function]
console.log(Object.prototype.toString.call(testSometing())) // [object String]

async function testSometing() {
    console.log("testSomething");
    return "return testSomething";
}
console.log(Object.prototype.toString.call(testSometing)) // [object AsyncFunction]
console.log(Object.prototype.toString.call(testSometing())) // [object Promise]
Copy the code

TestSomething () is already an async function and returns a Promise object. It needs to wait for it to resolve and push the Promise object to the queue. Then it clears the call stack first. The Promise is then executed.

update

I have received feedback from several friends that the timing of the last example is not consistent with the results of the current version. The reason may be that Chrome V8 has been updated for a year and a half since the end of this article. If you have Opera, other browsers that use older versions of Chrome’s kernel, or go to this address to download an older version of Chrome. I tested Opera, and there is no explanation for this in the Chrome V8 release documentation.

In previous releases, await functions required 3 ticks to be executed. In the current release, the V8 team violated the specification by not strictly following step 13 of promise-resolve-functions in order to improve performance. As a result, the 3 ticks were reduced by 2. The original

In Node 11, the mechanism has been unified with the browser. On the surface, you can expect await asyncfunctions to return promises as synchronous tasks.

The latter

More and more people are looking into async/await, which is said to be the ultimate solution for asynchronous programming, but most people don’t know much about how this method is executed internally

  1. Is a new way to write asynchronous code. The previous solutions for asynchronous code were callbacks and promises.
  2. Builds on a promise and is non-blocking like a PROMISE.
  3. Async /await makes asynchronous code look and behave more like synchronous code. This is where its power lies.

References: Understand JavaScript async/await