Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the asynchronous programming schemes of JS

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly talks about "what are the asynchronous programming solutions for JS". Interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "what are the asynchronous programming solutions for JS"?

Synchronous and asynchronous

We can understand that asynchronism means that a task is divided into two segments, first execute the * * paragraph, and then switch to other tasks, and then go back to the second paragraph when you are ready. The code that comes after the asynchronous task will run immediately without waiting for the asynchronous task to finish, that is, the asynchronous task does not have a "blocking" effect. For example, there is a task to read a file for processing, and the asynchronous execution process is as follows

This kind of discontinuous execution is called async. Accordingly, continuous execution is called synchronization.

Asynchronous mode is very important. On the browser side, long-time operations should be performed asynchronously to prevent the browser from losing its response. The example of * * is the Ajax operation. On the server side, "asynchronous mode" is even the only mode, because the execution environment is single-threaded, and if all http requests are allowed to be executed synchronously, server performance degrades sharply and quickly becomes unresponsive. Next, we will introduce six methods of asynchronous programming.

2. Callback function (Callback)

The callback function is the most basic method of asynchronous operation. The following code is an example of a callback function:

Ajax (url, () = > {/ / processing logic})

But the callback function has a fatal weakness, that is, it is easy to write callback hell (Callback hell). Assuming that multiple requests have dependencies, you might write the following code:

Ajax (url, () = > {/ / processing logic ajax (url1, () = > {/ / processing logic ajax (url2, () = > {/ / processing logic})}))

The advantage of callback function is simple, easy to understand and implement, but the disadvantage is that it is not conducive to the reading and maintenance of the code, and the high coupling between various parts makes the program structure chaotic and the process difficult to track (especially when multiple callback functions are nested). And only one callback function can be specified per task. In addition, it cannot use try catch to catch errors and cannot return directly.

III. Event monitoring

In this way, the execution of asynchronous tasks does not depend on the order of the code, but on whether an event occurs.

Here are two functions F1 and f2. The programming intention is that f2 must wait for F1 to complete before it can be executed. First, bind an event to F1 (the jQuery used here)

F1.on ('done', f2)

The above line of code means that when a done event occurs in F1, f2 is executed. Then, rewrite F1:

Function F1 () {setTimeout (function () {/ /... F1.trigger ('done');}, 1000);}

In the above code, f1.trigger ('done') indicates that the done event is triggered immediately after execution is completed, thus starting execution of f2.

The advantage of this approach is that it is easy to understand, multiple events can be bound, multiple callback functions can be specified for each event, and it can be "decoupled", which is conducive to modularization. The disadvantage is that the whole program will become event-driven, and the running process will become very unclear. When reading the code, it is difficult to see the main flow.

IV. Publish and subscribe

We assume that there is a "signal center". When a task is completed, a signal is "publish" to the signal center, and other tasks can "subscribe" the signal from the signal center to know when they can start execution. This is called the publish / subscribe pattern (publish-subscribe pattern), also known as the Observer pattern (observer pattern).

First, f2 subscribes the done signal to the signal center jQuery.

JQuery.subscribe ('done', f2)

Then, F1 makes the following rewriting:

Function F1 () {setTimeout (function () {/ /... JQuery.publish ('done');}, 1000);}

In the above code, jQuery.publish ('done') means that after F1 execution is completed, the done signal is issued to the signal center jQuery, thus triggering the execution of f2.

After f2 finishes execution, you can unsubscribe (unsubscribe)

JQuery.unsubscribe ('done', f2)

The nature of this method is similar to "event monitoring", but is significantly better than the latter. Because you can monitor the operation of the program by looking at the "message center" to find out how many signals exist and how many subscribers there are for each signal.

5. Promise/A+

Promise originally means promise, in the program, it means to promise that I will give you a result after a period of time. When will it take a while? The answer is asynchronous operation, which refers to those that may take a long time to get results, such as network requests, reading local files, etc.

Three states of 1.Promise

The initial state of the Pending----Promise object instance when it was created

Fulfilled---- can be understood as the state of success.

Rejected---- can be understood as the state of failure.

Once this commitment is changed from waiting state to other state, the state can never be changed. For example, once the state becomes resolved, it cannot be changed to Fulfilled again.

Let p = new Promise ((resolve, reject) = > {reject ('reject') resolve (' success') / / invalid code will not execute}) p.then (value = > {console.log (value)}, reason = > {console.log (reason) / / reject})

When we are constructing a Promise, the code inside the constructor is executed immediately

New Promise ((resolve, reject) = > {console.log ('new Promise') resolve (' success')}) console.log ('end') / / new Promise = > end

Chain call of 2.promise

Each call returns a new Promise instance (which is why then is available for chained calls)

If a result is returned in then, the result will be passed to the next successful callback in then

If an exception occurs in then, there will be the next failed callback of then.

If return is used in then, the value of return will be wrapped in Promise.resolve () (see example 1 and 2).

Parameters may not be passed in then, but will be passed to the next then if not passed (see example 3)

Catch will catch exceptions that are not caught.

Let's take a look at a few examples:

/ example 1 Promise.resolve (1) .then (res = > {console.log (res) return 2 / / packaged as Promise.resolve (2)}) .catch (err = > 3) .then (res = > console.log (res)) / / case 2 Promise.resolve (1) .then (x = > x + 1) .then (x = > {throw new Error ('My Error')}) .catch () = > 1 ) .then (x = > x + 1) .then (x = > console.log (x)) / / 2.catch (console.error) / / example 3 let fs = require ('fs') function read (url) {return new Promise ((resolve) Reject) = > {fs.readFile (url, 'utf8', (err, data) = > {if (err) reject (err) resolve (data)})} read ('. / name.txt') .then (function (data) {throw new Error () / / then will lead to the next then's failed callback}) / / because there is no failed callback in the next then It will continue to look down, and if none, it will be captured by catch. Then (function (data) {console.log ('data')}). Then (). Then (null, function (err) {console.log (' then', err) / / then error}) .catch (function (err) {console.log ('error')})

Promise can not only catch errors, but also solve the problem of callback hell. You can rewrite the previous callback hell example into the following code:

Ajax (url) .then (res = > {console.log (res) return ajax (url1)}) .then (res = > {console.log (res) return ajax (url2)}) .then (res = > console.log (res))

It also has some disadvantages, such as not being able to cancel Promise, and errors need to be caught through callback functions.

6. Generator Generators/ yield

Generator function is an asynchronous programming solution provided by ES6, and its syntax behavior is completely different from that of traditional functions. The characteristic of Generator is that it can control the execution of functions.

Syntactically, first of all, it can be understood that the Generator function is a state machine that encapsulates multiple internal states.

In addition to the state machine, the Generator function is also an ergodic object generation function.

The function can be paused, the yield can be paused, and the next method can be started, and each time the result of the expression after yield is returned.

The yield expression itself does not return a value, or always returns undefined. The next method can take a parameter that is treated as the return value of the previous yield expression.

Let's first look at an example:

Function * foo (x) {let y = 2 * (yield (x + 1)) let z = yield (y / 3) return (x + y + z)} let it = foo (5) console.log (it.next ()) / / = > {value: 6, done: false} console.log (it.next (12)) / / = > {value: 8, done: false} console.log (it.next (13)) / = > {value: 42, done: true}

The results may not be consistent with what you think, so let's analyze them line by line:

First of all, unlike ordinary functions, the Generator function call returns an iterator.

When performing * next times, passing parameters is ignored and the function is paused at yield (x + 1), so 5 + 1 = 6 is returned.

When the second next is executed, the parameter 12 passed in will be treated as the return value of the previous yield expression, and if you do not pass the parameter, yield will always return undefined. At this point let y = 2 12, so the second yield equals 2 12 / 3 = 8

When the third next is executed, the passed parameter 13 is treated as the return value of the previous yield expression, so z = 13, x = 5, y = 24, the sum equals 42

Let's look at another example: there are three local files, 1.txtPower2.txt and 3.txt, all with only one sentence. The next request depends on the result of the previous request. You want to call three files in turn through the Generator function.

/ / 1.txt file 2.txt//2.txt file 3.txt//3.txt file end let fs = require ('fs') function read (file) {return new Promise (function (resolve, reject) {fs.readFile (file,' utf8', function (err) Data) {if (err) reject (err) resolve (data)})} function* r () {let R1 = yield read ('. / 1.txt') let R2 = yield read (R1) let R3 = yield read (R2) console.log (R1) console.log (R2) console.log (R2)} let it = r () let {value Done} = it.next () value.then (function (data) {/ / value is promise console.log (data) / / data= > 2.txt let {value, done} = it.next (data) value.then (function (data) {console.log (data) / / data= > 3.txt let {value Done} = it.next (data) value.then (function (data) {console.log (data) / / data= > end})}) / / 2.txt = > 3.txt = > end

From the above example, we can see that it is troublesome to manually iterate the Generator function, and the implementation logic is a bit winding, but the actual development will generally be used in conjunction with the co library. Co is a generator-based process control tool for Node.js and browsers. With Promise, you can write non-blocking code in a more elegant way.

To install the co library, simply: npm install co

The above example can be easily implemented in two sentences.

Function* r () {let R1 = yield read ('. / 1.txt') let R2 = yield read (R1) let R2 = yield read (R2) console.log (R1) console.log (R2) console.log (R2)} let co = require ('co') co (r (). Then (function (data) {console.log (data)}) / / 2.txt= > 3.txt= > end = > undefined

We can use the Generator function to solve the callback hell problem. We can rewrite the previous callback hell example to the following code:

Function * fetch () {yield ajax (url,) = > {}) yield ajax (url1, () = > {}) yield ajax (url2, () = > {})} let it = fetch () let result1 = it.next () let result2 = it.next () let result3 = it.next ()

7. Async/await

Introduction to 1.Async/Await

With async/await, you can easily do what you did with the generator and the co function, with the following features:

Async/await is implemented based on Promise and cannot be used for ordinary callback functions.

Async/await, like Promise, is nonblocking.

Async/await makes asynchronous code look like synchronous code, which is its magic.

If a function adds async, then the function will return a Promise

Async function async1 () {return "1"} console.log (async1 ()) / /-> Promise {: "1"}

The Generator function calls three files in turn. That example is written in async/await and can be implemented in a few sentences.

Let fs = require ('fs') function read (file) {return new Promise (function (resolve, reject) {fs.readFile (file,' utf8', function (err, data) {if (err) reject (err) resolve (data)})} async function readResult (params) {try {let p1 = await read (params) 'utf8') / / await is followed by a Promise instance let p2 = await read (p1,' utf8') let p3 = await read (p2, 'utf8') console.log (' p1, p1) console.log ('p2, p2) console.log ('p3') P3) return p3} catch (error) {console.log (error)}} readResult ('1.txt'). Then (/ / async function also returns a promise data = > {console.log (data)}, err = > console.log (err)) / / p1 2.txt / / p2 3.txt / / p3 end / / end

2.Async/Await concurrent request

If you request two files, it has nothing to do with each other. You can use concurrent requests

Let fs = require ('fs') function read (file) {return new Promise (function (resolve, reject) {fs.readFile (file,' utf8', function (err) Data) {if (err) reject (err) resolve (data)})} function readAll () {read1 () read2 () / / this function is executed synchronously} async function read1 () {let r = await read ('1.txt.') console.log (r)} async function read2 () {let r = await read (' 2.txt') 'utf8') console.log (r)} readAll () / / 2.txt 3.txt here I believe that you have a deeper understanding of "what are the asynchronous programming solutions for JS", so you might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report