📜 ⬆️ ⬇️

[UPD] Chain.js: link synchronous and asynchronous functions in the chain

Chain.js is a small library made to create chains of synchronous and asynchronous functions. The idea of ​​chains was born after getting acquainted with Common JS Promises . The definition of “promises” itself says that promise is the meaning of performing one operation. If you want to invent, invent or create something, then you simply must try to link these operations into chains. Of course, you do not have to, and this is natural, but for me this has become the main motive. Before that, I did encounter some inconveniences in binding promise operations, although I expected that with this they would help me.

Start


The very existence of Common JS Promises I was known for a long time. I was pushed to mutual penetration by Angular.js , which has its promise / deferred implementation. Having suffered a little with the realization of those promise-based chains, it became clear that promises were not intended for this. Therefore, it was decided to reinvent the wheel and go on to make the necessary functionality on its own.

To business


In the course of thinking about the software interface, Chain.js acquired a list of 5 functions: 1 constructor and 4 methods. The compressed implementation has a size of 2.03KB, the full (no comment ^ _ ^) implementation has a size of 3.15KB. You can download these files on a page made specifically for Chain.js . No direct links, I'm afraid I can break.
Installation is trivial, no different from other scripts.

<script src="js/chain.dev.js" type="text/javascript"></script> 

After that, the library is available in the global scope ( window , apparently) under the name Chain . Chain is the constructor of the new chain and has two main call options (you can think up additional options yourself):
')
 var testChain = Chain(); //  var anotherChain = new Chain; 

Now we can feel all the power to create our chains, for this we have 3 methods:

The .then method accepts synchronous functions, .defer - asynchronous, .when - Chain objects. All 3 methods return a Chain object for which they are invoked (just like jQuery chaining ). Also, these methods can take either one required argument or an array of such arguments. For the .then and .defer result of the execution of the previous link is passed to the next in the specified function by the first argument.
The chain is executed only when the .end method is .end , it is the last library method.
Has such a signature:

The function will be called upon completion of all operations in the chain. Specifying a function is optional.
Examples for understanding:

 var calculate = Chain(); calculate. then(function() { //      undefined return 0; }). then(function(result) { //   , result  0 return result + 5; }). then(function(result) { // result  5 return result + 10; }). end(function(result) { console.log(result); }); //  15 

A different entry with the same result:

 var calculate = new Chain; function zero() { return 0; } function plus5(num) { return num + 5; } function plus10(num) { return num + 10; } function log(result) { console.log(result); } calculate. then([zero, plus5, plus10]). end(log); //  15 

Let's do the same asynchronously:

 var calculate = Chain(); calculate. defer(function(n, done) { //     undefined, //  - ,        done(0); }). defer(function(result, done) { // result  0 //    setTimeout(function() { done(result + 5); }, 1000); }). defer(function(result, done) { // result  5 done(result + 10); }). end(function(result) { console.log(result); }); //  15 

The same thing, in a different way:

 var calculate = new Chain; function zero(n, done) { done(0); } function plus5(num, done) { setTimeout(function() { done(num + 5); }, 1000); } function plus10(num, done) { done(num + 10); } function log(result) { console.log(result); } calculate. defer([zero, plus5, plus10]). end(log); //  15 

Finally, the .when method is used to connect the rest of your chains. After executing the .when method, the .when to the next link with the result of executing the previous chain links. Example:

 var five = Chain(), ten = Chain(); five.defer(function(n, done) { setTimeout(function() { done(5); }, 1000); }); ten. when(five). then(function(results) { return results[0] + 5; }); // results   [5] Chain(). when([ten, five, ten]). end(function(results) { console.log(results); }); //  [10, 5, 10] 


Work features


The chains passed to the .when method .when executed in parallel. The sequence in the resulting array will correspond to the sequence of connection (addition) of the specified chains, see the last example.

All functions transferred to the .end method after the start of the chain will wait for the chain to complete, that is, the chains will not be launched twice. Insert console.log into each function in the last example, it will become clearer.

The result of chain execution is saved and will be returned each time the .end method is .end ; the chain will not be started. In fact, the .end method can take the second argument, forcing the chain to start again, but this behavior is not brought to mind. If you like Chain.js , then I pledge to deal with this behavior.
Also, interruption of chain execution is not implemented, although it is possible and easy to implement.

the end


Is it the end? Welcome your comments, suggestions, wishes. Thanks for attention.

Update. Comparison with solutions in other libraries


After the third comment with a question on what Chain.js is different from other libraries, I was uncomfortable to be silent. I contacted KeepYourMind and asked him to help with the implementation of a simple task in when.js. KeepYourMind agreed to help and very soon showed an approximate solution to the proposed problem. For example, the following problem was proposed: asynchronously, we get the domain of the service of interest to us, then we generate a link to a specific address, we obtain data at that address, and show the data to the user. Roughly portray it with this view:

After that, I adapted the KeepYourMind solution example under Chain.js . Links to the Github Gist code:

Now you can compare the examples yourself and make your decision. If you want to add a solution using another library you can contact me, I will try to help you.

Also, during the discussion of the code with KeepYourMind , the idea of ​​expanding Chain.js was born in order to make it possible to use this solution. Thanks again for your attention.

Update number 2. Continuation


In the continuation of a brief discussion, KeepYourMind and can3p explained to me that all the described functionality is already present in the when.js library. So, I admit that Chain.js is only a bicycle. However, it remains true that this functionality is not fixed in Promises / A.

If you liked the examples of solutions proposed in the article and on the links, I advise you to get acquainted with when.js , which I will definitely do. Thank you all very much.

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


All Articles