ES6 async+await synchronous/asynchronous solution
This article mainly introduces the detailed explanation of ES6's async+await synchronization/asynchronous solution. This article uses the most concise way to unblock async + await. Those who are interested can learn more
Asynchronous programming has always been JavaScript programming major matters. Regarding asynchronous solutions, ES6 first saw the emergence of Promise based on state management, then the Generator function + co function, and then the ES7 async + await solution.
This article strives to unblock async + await in the most concise way.
Several scenarios of asynchronous programming
Let’s start with a common question: How to print the iteration sequence asynchronously in a for loop?
We can easily think of using closures or the let block-level scope specified in ES6 to answer this question.
for (let val of [1, 2, 3, 4]) { setTimeout(() => console.log(val),100); } // => 预期结果依次为:1, 2, 3, 4
What is described here is an asynchronous event that occurs evenly, and they are queued in the asynchronous queue in a predetermined order waiting for execution.
If asynchrony does not occur evenly, then the order in which they are registered in the asynchronous queue is out of order.
for (let val of [1, 2, 3, 4]) { setTimeout(() => console.log(val), 100 * Math.random()); } // => 实际结果是随机的,依次为:4, 2, 3, 1
The returned results are out of order and uncontrollable. This is the most realistic asynchronous. But another situation is that in a loop, what should you do if you want the previous asynchronous execution to be completed and the next asynchronous execution to be executed again?
for (let val of ['a', 'b', 'c', 'd']) { // a 执行完后,进入下一个循环 // 执行 b,依此类推 }
Isn’t this just multiple asynchronous “serials”!
The method of nesting asynchronous operations in the callback and then calling back solves this problem! Alternatively, using Promise + then() to nest layers can also solve the problem. However, if you insist on writing this nesting method in a loop, I'm afraid it will take a lot of trouble. I wonder, is there a better way?
Asynchronous synchronization solution
Just imagine, if you want to send a batch of data to the server, only the previous batch is sent successfully (that is, the server returns a successful response), Only then will the next batch of data be sent, otherwise the sending will be terminated. This is a typical example of "interdependent asynchronous operations in a for loop".
Obviously, this "serial" asynchronous can actually be regarded as synchronization. It takes more time than out-of-order asynchronous. Logically speaking, we want the program to execute asynchronously, just to "skip" blocking and spend less time. But on the contrary, if we need a series of asynchronous "serials", how should we program well?
For this "serial" asynchronous, ES6 can easily solve this problem.
async function task () { for (let val of [1, 2, 3, 4]) { // await 是要等待响应的 let result = await send(val); if (!result) { break; } } } task();
Literally, it is this cycle. When the results are obtained, the next cycle will be carried out. Therefore, the loop is paused ("stuck") every time it executes until the loop ends. This coding implementation effectively eliminates the problem of nested "callback hell" and reduces cognitive difficulty.
This is the solution for synchronizing asynchronous problems. Regarding this solution, if Promise mainly solves the problem of asynchronous callbacks, then async + await mainly solves the problem of synchronizing asynchronous problems and reducing the cognitive burden of asynchronous programming.
async + await "Different on the outside but the same on the inside"
When I came into contact with this API earlier, I looked at the cumbersome documentation and thought that async + await was mainly used to solve the problem. Asynchronous issues are synchronous.
actually not. As can be seen from the above example: the async keyword declares an asynchronous function. There is a line of await statements in the body of this asynchronous function, which notifies that the behavior is executed synchronously, and the adjacent codes above and below are executed line by line in sequence.
Translate this formal thing again, it is:
1. After the async function is executed, a promise object is always returned.
2. The line of statement where await is located is Synchronous
Among them, 1 shows that from the outside, the task method returns a Promise object after execution. Because it returns a Promise, it can be understood that the task is an asynchronous method. There is no doubt that it is used like this:
task().then((val) => {alert(val)}) .then((val) => {alert(val)})
2 illustrates that within the task function, asynchronous has been "cut" into synchronization. The whole thing is just a function that takes a little time to execute.
Comprehensive 1 and 2, from a formal point of view, "the task as a whole is an asynchronous function, and the entire internal part is synchronous", which is referred to as "different on the outside and the same on the inside".
The whole is an asynchronous function, which is not difficult to understand. In terms of implementation, we might as well reverse it. At the language level, when the async keyword is called, a promise is forced to be added at the end of the function execution. The response:
async fn () { let result; // ... //末尾返回 promise return isPromise(result)? result : Promise.resolve(undefined); }
is internally synchronous How is it done? In fact, the await call causes the following statements (functions) to be executed recursively. It will not be resolved until the result is obtained and its status is changed. Only after the resolve is resolved, the await line of code will be considered completed and will continue. Execute to the next line. Therefore, although there is a large for loop outside, the entire for loop is serialized in sequence.
Therefore, it is not difficult to understand the meaning of async + await just from the appearance of the above framework. It's just that simple to use, but Promise is a basic piece that must be mastered.
秉承本次《重读 ES6》系列的原则,不过多追求理解细节和具体实现过程。我们继续巩固一下这个 “形式化” 的理解。
async + await 的进一步理解
有这样的一个异步操作 longTimeTask,已经用 Promise 进行了包装。借助该函数进行一系列验证。
const longTimeTask = function (time) { return new Promise((resolve, reject) => { setTimeout(()=>{ console.log(`等了 ${time||'xx'} 年,终于回信了`); resolve({'msg': 'task done'}); }, time||1000) }) }
async 函数的执行情况
如果,想查看 async exec1 函数的返回结果,以及 await 命令的执行结果:
const exec1 = async function () { let result = await longTimeTask(); console.log('result after long time ===>', result); } // 查看函数内部执行顺序 exec1(); // => 等了 xx 年,终于回信了 // => result after long time ===> Object {msg: "task done"} //查看函数总体返回值 console.log(exec1()); // => Promise {[[PromiseStatus]]: "pending",...} // => 同上
以上 2 步执行,清晰的证明了 exec1 函数体内是同步、逐行逐行执行的,即先执行完异步操作,然后进行 console.log() 打印。而 exec1() 的执行结果就直接是一个 Promise,因为它最先会蹦出来一串 Promise ...,然后才是 exec1 函数的内部执行日志。
因此,所有验证,完全符合 整体是一个异步函数,内部整个是同步的 的总结。
await 如何执行其后语句?
回到 await ,看看它是如何执行其后边的语句的。假设:让 longTimeTask() 后边直接带 then() 回调,分两种情况:
1)then() 中不再返回任何东西
2) then() 中继续手动返回另一个 promise
const exec2 = async function () { let result = await longTimeTask().then((res) => { console.log('then ===>', res.msg); res.msg = `${res.msg} then refrash message`; // 注释掉这条 return 或 手动返回一个 promise return Promise.resolve(res); }); console.log('result after await ===>', result.msg); } exec2(); // => 情况一 TypeError: Cannot read property 'msg' of undefined // => 情况二 正常
首先,longTimeTask() 加上再多得 then() 回调,也不过是放在了它的回调列队 queue 里了。也就是说,await 命令之后始终是一条 表达式语句,只不过上述代码书写方式比较让人迷惑。(比较好的实践建议是,将 longTimeTask 方法身后的 then() 移入 longTimeTask 函数体封装起来)
其次,手动返回另一个 promise 和什么也不返回,关系到 longTimeTask() 方法最终 resolve 出去的内容不一样。换句话说,await 命令会提取其后边的promise 的 resolve 结果,进而直接导致 result 的不同。
值得强调的是,await 命令只认 resolve 结果,对 reject 结果报错。不妨用以下的 return 语句替换上述 return 进行验证。
return Promise.reject(res);
最后
其实,关于异步编程还有很多可以梳理的,比如跨模块的异步编程、异步的单元测试、异步的错误处理以及什么是好的实践。All in all, 限于篇幅,不在此汇总了。最后,async + await 确实是一个很优雅的方案。
相关推荐:
The above is the detailed content of ES6 async+await synchronous/asynchronous solution. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Generally speaking, we only need to use one of the headphones or speakers at the same time. However, some friends have reported that in the win11 system, they encountered the problem of headphones and speakers sounding at the same time. In fact, we can turn it off in the realtek panel and it will be fine. , let’s take a look below. What should I do if my headphones and speakers sound together in win11? 1. First find and open the "Control Panel" on the desktop. 2. Enter the control panel, find and open "Hardware and Sound" 3. Then find the "Realtek High Definition" with a speaker icon. Audio Manager" 4. Select "Speakers" and click "Rear Panel" to enter the speaker settings. 5. After opening, we can see the device type. If you want to turn off the headphones, uncheck "Headphones".

When you find that one or more items in your sync folder do not match the error message in Outlook, it may be because you updated or canceled meeting items. In this case, you will see an error message saying that your local version of the data conflicts with the remote copy. This situation usually happens in Outlook desktop application. One or more items in the folder you synced do not match. To resolve the conflict, open the projects and try the operation again. Fix One or more items in synced folders do not match Outlook error In Outlook desktop version, you may encounter issues when local calendar items conflict with the server copy. Fortunately, though, there are some simple ways to help

Artificial intelligence is a computing system that attempts to imitate human intelligence, including some human functions that are intuitively related to intelligence, such as learning, problem solving, and rational thinking and action. Broadly interpreted, the term AI covers many closely related fields such as machine learning. Systems that make heavy use of AI are having significant social impacts in areas such as healthcare, transportation, finance, social networks, e-commerce, and education. This growing social impact has also brought with it a series of risks and concerns, including errors in artificial intelligence software, cyberattacks and artificial intelligence system security. Therefore, the issue of verification of AI systems, and the broader topic of trustworthy AI, has begun to attract attention from the research community. “Verifiable AI” has been confirmed

MySQL is a very popular open source relational database management system that is widely used in various web applications, enterprise systems, etc. In modern business application scenarios, most MySQL databases need to be deployed on multiple servers to provide higher availability and performance, which requires MySQL data migration and synchronization. This article will introduce how to implement MySQL data migration and synchronization between multiple servers. 1. MySQL data migration MySQL data migration refers to the data migration in the MySQL server.

A very useful function of win10 clipboard is the cross-device cloud storage function, which is very useful and can help users copy and paste simultaneously on PC devices and mobile devices. The setting method is very simple, just set it on the clipboard in the system. Synchronize win10 clipboard to mobile phone 1. First click Start in the lower left corner to enter settings. 2. Then click "System". 3. Select "Clipboard" on the left. 4. Finally, click Login in "Cross-device synchronization" on the right, and then select your mobile phone.

The OneDrive app on your system stores all your files and folders in the cloud. But sometimes users don't want certain files or folders to be stored and take up OneDrive space that is limited to 5 GB without a subscription. To do this, there is a setting in the OneDrive app that allows users to select files or folders to sync on the cloud. If you are also looking for this, then this article will help you select folders or files to sync in OneDrive on Windows 11. How to select certain folders to sync in OneDrive in Windows 11 Note: Make sure the OneDrive app is connected and synced

Thread pool optimization solution in PHP high concurrency processing With the rapid development of the Internet and the continuous growth of user needs, high concurrency has become an important issue in modern Web application development. In PHP, handling high concurrent requests is a challenge due to its single-threaded nature. In order to solve this problem, introducing the concept of thread pool is an effective optimization solution. A thread pool is a reusable collection of threads used to perform a large number of concurrent tasks. Its basic idea is to separate the creation, destruction and management of threads, and reduce the number of threads by reusing threads.

Locks and Synchronization in Concurrent Programming In concurrent programming, multiple processes or threads run simultaneously, which can lead to resource contention and inconsistency issues. To solve these problems, locks and synchronization mechanisms are needed to coordinate access to shared resources. Concept of Lock A lock is a mechanism that allows only one thread or process to access a shared resource at a time. When one thread or process acquires a lock, other threads or processes are blocked from accessing the resource until the lock is released. Types of locks There are several types of locks in python: Mutex lock (Mutex): ensures that only one thread or process can access resources at a time. Condition variable: Allows a thread or process to wait for a certain condition and then acquire the lock. Read-write lock: allows multiple threads to read resources at the same time, but only allows one thread to write resources
