stay Javascript On the previous article of asynchronous programming Javascript Asynchronous in , I've made a brief statement “Javascript Asynchronous principle in ”,“Javascript How to realize asynchronous call on single thread ” as well as “Javascript Timer in ” And other related issues .

I will talk about it in this article Javascript Several asynchronous programming models commonly used in .

In the front-end code writing , Asynchronous scenes are everywhere . Such as mouse click , Keyboard enter , Network requests and other operations closely related to the browser , For example, some delayed interactive effects and so on .

In these scenarios , You have to use the so-called “ Asynchronous mode ”, Otherwise, the feasibility and user experience of the program will be serious . We list several asynchronous programming models commonly used in these scenarios , include
Callback function , event listeners , Observer model ( Message subscription / release ),promise pattern . In addition, I will introduce it a little bit ES6(ES7) New scheme in .

We will describe each programming model below .

<> Callback function

The callback function can be said to be Javascript The most basic method of asynchronous programming . Let's imagine a scene like this , We need to show a duration on the page 3 Second loading
Visual style , And then show what we really want to show on the page . The sample code is as follows ,
// more code function loading(callback) { // continued 3 Second loading Exhibition setTimeout(function
() { callback(); }, 3000); } function show() { // Show real data to users } loading(show); //
more code
In code loading(show) It's a function show() As a function loading() Parameters of . stay loading() complete 3 Second loading
after , Then execute the callback function ( The example uses the setTimeout To simulate ). In this way ,show() It becomes an asynchronous call , Its implementation has been postponed to loading() Just before it's finished .

<> Defects in callback functions

A callback function is often a call to a user provided function , The function is often provided in the form of parameters . Callback functions are not necessarily executed asynchronously . The feature of callback function is easy to use , Easy to understand . The disadvantage is that there is a certain coupling between logic . The most disgusting thing is that it causes so-called
callback hell. For example, here is an example ,
A(function () { B(function () { C(function() { D(function() { // ... }) }) }) }
In the example A,B,C,D The four tasks are dependent , Through function callback , The code will look like this . Both maintainability and readability are very poor .

In addition to the problem of callback nesting , There may be another problem , It is inconvenient to control the process . For example, we want to send 3 Requests , When 3 When all requests return , We'll do the logic , So the code might be ,
var count = 0 for (var i = 0; i < 3; i++) { request('source_' + i, function ()
{ count++; if (count === 3) { // do my logic } }); }
In the example code above , I passed request Yes, three url A request was sent , But I don't know the return of these three requests . But I added a counter count
, Counter judgment is performed in each callback request , When the counter is 3 All three requests have been returned successfully , At this point, go to the relevant task . obvious , In this case, the process control is ugly .

last , Sometimes we want the robustness of the program , One may be needed try...catch grammar . such as ,
// demo1 try { setTimeout(function () { throw new Error('error occured'); }) }
catch(e) { console.log(e); } // demo2 setTimeout(function () { try { // your
logic } catch(e) { } });
In the example code above , If we look like demo1 That would try...catch Add to asynchronous logic , Even if an exception occurs in an asynchronous call, we can't catch it , because try...catch
Future exceptions cannot be caught . but , We can only look like demo2 That would try...catch Statement blocks are placed in specific asynchronous logic . In this way, once asynchronous calls are made more often , Then there will be a lot more
try...catch. This is definitely not good .

In addition to the above problems , I think the real core problem with callback functions is that , Nested return functions often destroy the call stack of the entire program , And like return,throw
These keywords used for code flow control can not be used normally ( Because the previous callback function often affects all the following callback functions ).

<> event listeners

Event monitoring in UI Programming is everywhere . For example, I bind a button to a click event , Bind an input box to a keyboard event, etc . For example, the following code ,
$('#button').on('click', function () { console.log(' I was ordered '); });
It's used on it JQuery The grammar of , An event is bound to a button . When the event is triggered , Will execute the logic of the binding . This is easier to understand .

In addition to interface events , Usually we have all kinds of network request events , such as ajax,websocket
wait . These network requests also trigger various events at different stages , If the program has binding related processing logic , When the event is triggered, the relevant logic is executed .

besides , We can also customize events . such as ,
$('#div').on('data-loaded', function () { console.log('data loaded'); }); $(
It adopts JQuery The grammar of , We customized an event , be called ”data-loaded”, A trigger logic is defined on this event . When we pass trigger
When this event is triggered , The logic of the previous binding will be executed .

<> Observer model

Custom events were mentioned earlier in event monitoring , In fact, the custom event is a concrete manifestation of the observer pattern . Observer model , Also known as message subscription / Publishing mode . What it means is , Let's start with one “ Signal center ”, When a task is completed, a signal is sent to the signal center ( event ), Then the signal center will broadcast after receiving this signal . If other tasks subscribe to the signal , Then these tasks will receive a notification , Then the logic related to the task is performed .

Here is a simple implementation of the observer pattern ( Please refer to AngularJS Implement observer mode ),
var ob = { channels: [], subscribe: function(topic, callback) { if (!_.isArray(
this.channels[topic])) { channels[topic] = []; } var handlers = channels[topic];
handlers.push(callback); }, unsubscribe: function(topic, callback) { if (!_.
isArray(this.channels[topic])) { return; } var handlers = this.channels[topic];
var index = _.indexOf(handlers, callback); if (index >= 0) { handlers.splice(
index, 1); } }, publish: function(topic, data) { var self = this; var handlers =
this.channels[topic] || []; _.each(handlers, function(handler) { try { handler.
apply(self, [data]); } catch (ex) { console.log(ex); } }); } };
Its usage is as follows ,
ob.subscribe('done', function () { console.log('done'); }); setTimeout(function
() { ob.publish('done') }, 1000);
There are many ways to implement the observer pattern , But the basic core is the same , There will be news subscription and publishing . In essence , The event monitoring mentioned above is also an observer mode .

The observer model has many advantages when used well , The ability to decouple is quite good . But for complex systems, if you want to use observer mode for logic , We must do a good job in the design of event subscription and publication , Otherwise, it will lead to the program running process confusion .

<>Promise pattern

Promise Strictly speaking, it's not a new technology , It's just a grammar sugar , A mechanism , A code structure and process , Used to manage asynchronous callbacks .

jQuery Medium Promise Implementation from Promises/A standard . use promise To manage callbacks , You can flatten the callback logic , Can avoid the aforementioned callback hell . The sample code is as follows ,
function fn1() { var dfd = $.Deferred(); setTimeout(function () { console.log(
'fn1'); dfd.resolve(); }, 1000); return dfd.promise(); } function fn2() {
console.log('fn2'); } fn1().then(fn2);
For the previous mentioned callback hell and exception difficult to catch , use promise Can be easily solved .
see , It's all in one line . But use promise Processing asynchronous calls , There is one thing to note , It's all asynchronous functions promise turn . so-called promise
This means that asynchronous functions need to be encapsulated , Let it return one promise object . such as ,
function A() { var promise = new Promise(function (resolve, reject) { // your
logic }); return promise; }
<>ES6 Solutions in

ES6 This year 6 It's officially released around January . Many new contents have been added . There are two things that might be used to resolve the content of an asynchronous callback .

<>ES6 Medium Promise

Newly released ECMAScript2015 Already covered in promise Related content of , however ES6 Medium Promise Norms are Promise/A+
standard , It can be said that it is Promise/A Enhanced version of the specification .

Modern browser Chrome,Firefox And so on Promise Provides native support . Detailed documentation can be found MDN.

In short ,ES6 in promise The contents are as follows ,

* promise There are three states :pending( wait for ),fulfilled( success ),rejected( fail ). among pending Is the initial state .
* promise State transition of can only be :pending->fulfilled perhaps pending->rejected. The direction of conversion cannot be reversed , And fulfilled and
rejected States cannot be converted to each other . Each state transition triggers a related call .
* pending->fulfilled Time ,promise There will be one value( Value of success status );pending->rejected Time ,promise
There will be one reason( Reason for failure status )
* promise have then method .then Method must return a promise.then You can chain call multiple times , And the order of callback follows then The order of declaration is consistent .
* then Method takes two parameters , namely “pending->fulfilled” Call and “pending->rejected” Call of .
* then You can take another one promise example , You can also accept one thenable( class then Object or method ) example .
Generally speaking promise The content is relatively simple , It involves three states and two state transitions . actually promise At the core of then Method implementation .

Here's from MDN upper Promise Code example for ( A little change ),
var p1 = new Promise(function (resolve, reject) { console.log('p1 start');
setTimeout(function() { resolve('p1 resolved'); }, 2000); }); p1.then(function (
value) { console.log(value); }, function(reason) { console.log(reason); });
The execution result of the above code is , Print first ”p1 start” And then pass by 2 Print again in about seconds ”p1 resolved”.

Of course, we can also add multiple callbacks . We can go through the previous one then Call in method return take promise Pass it back . such as ,
p1.then(function(v) { console.log('1: ', v); return v + ' 2'; }).then(function(
v) { console.log('2: ', v); });
But in use Promise When , There are some things to pay attention to , This article We have a problem with
promises( Translation ) It's summed up very well , If you are interested, please refer to it .

No matter what ES6 Medium promise still jQuery Medium promise/deferred, Indeed, the nesting problem of asynchronous code can be avoided , Make the whole code structure clear , No need to take it again
callback hell torment . But it just stops there , Because it didn't touch js The real core of asynchronous callback .

Now the industry has a lot to say about PromiseA+ Implementation of specification , But the blogger feels that bluebird It's a good library , It's worth it , If you have choice difficulties , Try it ???

<>ES6 in Generator

ES6 Introduced in Generator It can be understood as an implementation mechanism of coprocess , It allows functions to Javascript The execution power is handed over to other functions ( code ), And return to continue when necessary .

We can use it Generator coordination ES6 in Promise, Further flattening asynchronous calls ( Turn into a synchronized style ).

Let's take an example ,
function* gen() { var ret = yield new Promise(function(resolve, reject) {
console.log('async task start'); setTimeout(function() { resolve('async task
end'); }, 2000); }); console.log(ret); }
above Node.js In code , We define a Generator function , And created a promise,promise Internal use setTimeout An asynchronous task is simulated .

Now we're going to do this Generator function , because yield It's a promise, So we need to use then method ,
var g = gen(); var result =; result.value.then(function(str){ console.
log(str); // Yes resolve Data repackaging , And pass it on to the next promise return { msg: str }; }).then(
function(data){; });
The final result is as follows ,
async task start // after 2 About seconds async task end {msg: 'async task end'}
Actually about Generator There is a lot more to say , Because of the space, it will not be expanded here . The industry already has a Generator Library for handling asynchronous calls , such as co,task.js

<>ES7 Medium async and await

In single threaded Javascript Do asynchronous tasks on ( Even concurrent tasks ) It's a real headache , There will always be all kinds of problems . Callback from the earliest function , reach Promise, Again Generator, Emerging solutions , Although they have improved , But it still makes people feel that there is no complete solution to this problem .

For example , I just want to read a file right now , Such a simple thing , Why think so much ? It's a callback again , again promise
Of , Are you bored . I want to write code as simple as this , Can't you ?
function task() { var file1Content = readFile('file1path'); var file2Content =
readFile(fileContent); console.log(file2Content); }
What you want to do is simple , Read the first file , Its content is the name of the second file to read .

Fortunately ,ES7 Medium async and await Can help you do it . But it needs to be changed a little ,
async function task() { var file1Content = await readFile('file1path'); var
file2Content= await readFile(fileContent); console.log(file2Content); }
see , The changes are simple , As long as task Add key words before it async, Add before asynchronous tasks within a function await
Just make a statement . If you ignore these extra keywords , It's a complete synchronization .

actually , This method is mentioned in the front end Generator and Promise Package of the scheme .ECMAScript The organization also believes that this is the current solution Javascript The best scheme of asynchronous callback , So it may be in the ES7 It should be included in the specification . It should be noted that , This feature is ES7 Proposal for , rely on Generator, So use it with caution ( It doesn't work at the moment )!


In addition to the above several options , In fact, there is another plan . It is to solve the problem of asynchronous call on single thread by using coprocessor .

We mentioned that before ,Generator Of yield You can pause function execution , Temporary transfer of executive power to other tasks , After other tasks are completed , Return the right of execution . This is actually the basic model of coprocessing .

The industry has a model based on V8 Server development framework of engine fibjs, Its implementation mechanism follows Node.js It's not the same .fibjs use fiber solve v8 Multiplexing of engine , And through a large number of c++ assembly , Delegate heavy load operations to background threads , release v8 thread , Strive for more concurrency time .

in a word ,fibjs From the bottom , The fiber model solves the problem of asynchronous call . about fibjs, If you are interested, please refer to the relevant information . But I'm very cautious about it . The reasons are as follows ,

* Ecological reasons .
* Used js, But it was abandoned js Asynchrony of .
But it can be studied as an interest .

©2019-2020 Toolsou All rights reserved,
Final review of database : Summary of comprehensive application questions Laplance operator ( Second derivative ) Simple learning of computer composition principle pyqt Button call python program _PyQt: Link button to function in program How much can you go up once you change jobs ? Today, I saw the ceiling of job hopping python in str Function usage _python in str Usage Summary of built-in functions MySQL trigger web The server nginx---linux Installation and deployment C++ Chapter V polymorphism exercises :( It's coming to an end )python Check built-in functions , How to check python Built in function