📜 ⬆️ ⬇️

Asynchronous function sequential call

As is known, the JavaScript language pursues the event-oriented programming paradigm. This is certainly good, but what to do if, after one asynchronous function, another asynchronous function is called, and then another, and another ... Sometimes such code is very confusing, and not only the person who is used to the synchronous and alternate function calls. This applies to complex animations, timeouts, Ajax, when one must be followed by another, and so on.

Therefore, I developed my crutch, which allows you to more visually call asynchronous functions that trigger a callback after execution. It is likely that the solution has long existed, but, unfortunately, I have not found such a solution.

UPD
image
Below is my solution, which is an analogue of this function of the async module and a heap of other similar solutions presented in the comments. Thanks to all the commentators and sedictor in particular.
/ UPD
')
Consider an example (which is taken from the head and errors are possible in it) of the hypothetical site parser, which after parsing enters the data into the database, and, after entering, causes some code.

var html = ''; request.on('response', function (response) { response.on('data', function (chunk) { html = html + chunk; }); response.on('end', function() { //-  parse(html, function(data){ //- ,     addToDatabase(data, function() { doSomething(); }) }); }); }); 


Many nested kolbekov - not gud, we try differently.

 var html = ''; var responceOnEnd = function() { parse(html, parsed); } var parsed = function(data){ addToDatabase(data, addedToDatabase) } var addedToDatabase = function() { doSomething(); } request.on('response', function (response) { response.on('data', function (chunk) { html = html + chunk; }); response.on('end', responceOnEnd); }); 


But here are a few extra variables in which you can also get confused.

I suggest doing this:

 wait(function(runNext){ request.on('response', runNext); }).wait(function(runNext, response){ response.on('data', function (chunk) { html = html + chunk; }); response.on('end', function() { runNext(html); }); }).wait(function(runNext, html){ parse(html, runNext); }).wait(function(runNext, data){ addToDatabase(data, runNext); }).wait(function(){ doSomething(); }) 


Interesting? Let's go further.

Function wait.

 //first —  ,   wait = function(first){ //       return new (function(){ var self = this; var callback = function(){ var args; if(self.deferred.length) { /*       */ args = [].slice.call(arguments); /*    -     */ args.unshift(callback); //      self.deferred[0].apply(self, args); //     self.deferred.shift(); } } this.deferred = []; //    this.wait = function(run){ //      this.deferred.push(run); // this      return self; } first(callback); //   }); } 


I'm not sure that the code and comments are transparent, I have to think about it myself for a few seconds :)

For clarity, I made several sequential animations:

  wait(function(runNext){ log('  '); $('#div1').animate({ top: 30 }, 1000, function(){ // -     runNext(1,2); }); }).wait(function(runNext, a, b){ //     log('  , a='+a+' b='+b ); $('#div2').animate({ top: 50 }, 1000, runNext); }).wait(function(runNext){ log('  '); setTimeout(function(){ log('  ') runNext(); }, 2000); }).wait(function(runNext){ log('  '); $('#div3').animate({ left: 50 }, 1000, runNext); }).wait(function(runNext){ log(' '); $('#div1').animate({ top: 0, left: 45 }, 1000, runNext); }).wait(function(){ log(''); }); 
Run an example on JSFidle

How it works?
The first thing to do is to call the function wait, whose argument is another function that runs immediately with one argument that serves as a callback (in the example, it is defined as runNext) to call the next portion of code. After the callback is executed, to which you can pass some arguments received at the current step, the next function called in the wait method is called, the first argument of this function is the callback calling the next part of the script, the rest are the arguments passed to the callback in the previous step. And so on.

Actually, everything.
PS As stated above, I’m not sure of the uniqueness of this development, so if the Chabrasoobshchestvo evaluates this short article as a commonplace, it will quietly go to drafts.
Judging by the number of people who added the article to the favorites, the post has some value, so, perhaps, I will not hide it.

Source: https://habr.com/ru/post/134823/


All Articles