cool hit counter stress (on a syllable)ES6-async+await synchronize/ Asynchronous solutions_Intefrankly

stress (on a syllable)ES6-async+await synchronize/ Asynchronous solutions

Asynchronous programming has always been a big thing in JavaScript programming. With respect to asynchronous solutions, ES6 saw the emergence of state-managed Promise, then Generator functions + co functions, followed by ES7's async + await solution.

This article seeks to untangle async + await in the most concise way possible.

A few scenarios for asynchronous programming

Let's start with a common problem: How to print the iteration order asynchronously in a for loop?

It's easy to think of using closures, or let block scopes as mandated by ES6, to answer this question.

for (let val of [1, 2, 3, 4]) { settimeout(() => console.log(val),100);}// => The expected results, in order, are:1, 2, 3, 4

Described here is an evenly occurring asynchrony where they are sequentially queued in an asynchronous queue waiting to be executed in a given order.

If the asynchrony does not occur evenly, then the order in which they are registered in the asynchronous queue is disordered.

for (let val of [1, 2, 3, 4]) { settimeout(() => console.log(val), 100 * Math.random());}// => The actual results are random, in order:4, 2, 3, 1

The returned result is messy uncontrollable, which would have been the most realistic asynchrony. But another situation is that in a loop, what if you want the previous asynchronous execution to finish and the latter asynchronous execution again?

for (let val of ['a', 'b', 'c', 'd']) { // a After execution, Go to the next cycle // execute b, and so on}

Isn't this just multiple asynchronous "serials"!

Doesn't nesting the asynchronous operation in the callback callback and then calling it back solve this problem! Alternatively, using Promise + then() layers of nesting will also solve the problem. However, I'm afraid it would still take some effort to write this nesting in a loop the hard way. Try to ask, is there a better way?

   Asynchronous Synchronization Program

just think!, If you are going to send a batch of data to the server, Only the previous batch was sent successfully( That is, the server returns a successful response), Before starting the next batch of data, Otherwise terminate the transmission。 Here it is. A typical “for There are interdependent asynchronous operations in the loop” examples of。

Obviously, this "serial" asynchrony can essentially be treated as synchronous. It takes more time compared to chaotic asynchronous. By definition, we want the program to execute asynchronously just to "skip" the blocking and spend less time. But in contrast, if a series of asynchronous "serials" are required, how should we program them nicely?

For this "serial" asynchrony, the problem is very easily solved with ES6.

async function task () { for (let val of [1, 2, 3, 4]) { // await is to wait for the response let result = await send(val); if (!result) { break; } }}task();

Literally, it's this cycle, wait for a result, and then proceed to the next cycle. Thus, the loop is paused ("stuck") once for each execution until the loop ends. This coding implementation does a good job of eliminating the "callback hell" problem of nesting layers and reducing cognitive difficulty.

Here it is. Options for synchronizing asynchronous problems . With respect to this solution, if Promise primarily addresses asynchronous callbacks, async + await primarily addresses synchronizing asynchronous problems and reducing the cognitive burden of asynchronous programming.

   async + await "different outside, same inside"

When I first came across this API, I looked at the cumbersome documentation and half-understood that async + await was mainly for synchronizing asynchronous problems.

Actually, no. From the above example: the async keyword declares an asynchronous function that has an await statement inside the body of the asynchronous function, which announces that the behavior is executed synchronously and is executed sequentially line by line with the adjacent code above and below.

To translate this formalization a little further, it is.

1. The async function always returns a promise object after execution

2. The line where the await statement is located is synchronized

where 1 shows that externally, the task method returns a Promise object after execution, and because it returns a Promise, it is understood that task is an asynchronous method. No doubt it is used like this.

task().then((val) => ) .then((val) => )

2 illustrates that inside the task function, asynchrony has been "chipped" into synchronization. The whole thing is just a function that is slightly time consuming to execute.

Combining 1 and 2, formally, is "task The whole is an asynchronous function, the whole is synchronous internally ", or "different outside, same inside".

The overall is an asynchronous function Not hard to understand. In terms of implementation, we might as well reverse the process and have the language level make the async keyword call force a promise backtrack at the end of the function execution: the

async fn () { let result; // ... // End return promise return isPromise(result)? result : Promise.resolve(undefined);}

It's synchronized internally. - How is that done? The await call actually makes the subsequent statement (function) do a recursive execution until it gets the result and changes its state, then it resolves, and only when it resolves does the await line of code finish executing and move on to the next line. So, even though the outside is a big for loop, the whole for loop is sequentially serial.

So it's not hard to understand the meaning of async + await just from the appearance of the above framework. It's just as simple to use, but instead Promise is a fundamental piece that must be mastered.

In keeping with the principles of this Rereading ES6 series, it is not too much of a quest to understand the details and specific implementation process. Let's continue to consolidate this "formalized" understanding.

   Further understanding of async + await

There is such an asynchronous operation as longTimeTask, which has been wrapped in a Promise. A series of validations are performed with the help of this function.

const longTimeTask = function (time) { return new Promise((resolve, reject) => { setTimeout(()=>{ console.log(` wait for $ year, Finally, a reply.`); resolve({'msg': 'task done'}); }, time||1000) })}

Execution of the async function

If, for example, you want to see the result returned by the async exec1 function, and the result of the await command execution.

const exec1 = async function () { let result = await longTimeTask(); console.log('result after long time ===>', result);}// View the order of execution within a functionexec1();// => wait for xx year, Finally, a reply.// => result after long time ===> Object // View the overall return value of the functionconsole.log(exec1());// => Promise {[[PromiseStatus]]: "pending",...}// => ibid

The above 2-step execution clearly demonstrates that the exec1 function is executed synchronously, line by line, inside the exec1 function, i.e. the asynchronous operation is executed first, and then the console.log() is printed. The result of exec1() is a straightforward Promise, because it pops out a string of Promise ... first, before the internal execution log of the exec1 function.

Thus, all validation, fully consistent with The whole is an asynchronous function, the whole is synchronous internally The summary.

How does await execute subsequent statements?

Go back to await and see how it executes the statements that follow it. Hypothesis: let longTimeTask() be followed directly by then() callback in two cases.

1) Nothing is returned in then() anymore

2) continue to manually return another promise in then()

const exec2 = async function () { let result = await longTimeTask().then((res) => { console.log('then ===>', res.msg); res.msg = `$ then refrash message`; // Comment out this article return perhaps Manually return a promise return Promise.resolve(res); }); console.log('result after await ===>', result.msg);}exec2();// => Situation I TypeError: Cannot read property 'msg' of undefined// => Situation two normal

First of all, longTimeTask() plus more then() callbacks are just placed in its queue of callbacks. That is, the await command is always followed by an expression statement, but the way the code is written is confusing. (A better practice suggestion is to move the then() behind the longTimeTask method into the longTimeTask function body and wrap it)

Second, manually returning another promise is not the same as returning nothing at all in relation to what the longTimeTask() method ultimately resolves out. In other words, the await command extracts the resolve result of the promise that follows it, which in turn directly causes the result to be different.

It is worth emphasizing that the await command only recognizes resolve results and reports an error for reject results. You may wish to replace the above return with the following return statement to verify.

return Promise.reject(res);


indeed, There's a lot more to sort out about asynchronous programming, For example, asynchronous programming across modules、 Asynchronous unit testing、 Asynchronous error handling and what is good practice。All in all, Limitations on space, Not to be summarized here。 lastly,async + await A very elegant solution indeed。


1、FAST FACTSThe countrys first set of artificial intelligence textbooks will enter primary and secondary schools next year and the response to the pilot in Shanghai has been overwhelming
2、linux network programming sockets xi socket IO timeout setting method and timeout with select
3、Access to Gaga Packaging SDK one click for all handicap channels
4、Remembering a zookeeper connection spike primary
5、The story behind the success of Pepper the robot

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送