Recently too Busy, originally a weekly article, one months also did not write an article. Hey!
Next, the intention of the blog to make a revision, may change the blog address, good earnest writing articles, the future of the blog content will be divided into the following several directions:
Bloggers write their own technical articles
Foreign technical Articles Translation
Bo main spit groove, sense, egg-like article
I wish I could do it well.
What is a callback to hell?
PS: Some Daniel said, there is no multi-layer callback nesting, write more people will have.
Here's an example
When using the jquery Animat to do multiple animations, many of the children's shoes may have written the following code.
The code is as follows |
Copy Code |
After the previous animation completes, the next animation is executed immediately after execution $ (' xx '). Animate ({xxxx}, function () { $ (' xx '). Animate ({xx},function () { Do something },1000) },1000)
|
As you can see from the above code, there are currently 2 levels of callback nesting.
So let's think about it, if we have 3, 4, or more animations to execute immediately,
Did we find that I was caught in an endless callback to hell?
You can visit here to see some of the callbacks we usually write. More examples: Callback in JS code hell
So, here, you see, a lot of callback functions are nested,
Not only makes the code look uglier and bloated, it also makes the project more and more difficult to maintain.
So, we have to find a way to avoid such a code appearing in our project.
The benefits and annoyances of asynchronous programming
The JavaScript engine is single-threaded, but with asynchronous programming, the Nodejs that runs on the server side has high performance.
It also has the ability to perform IO operations in parallel, which makes it possible for many child shoes to write a number of callback nesting code.
Make our code look ugly. Of course, this is not the problem of the JS language itself, like the beginning of the written:
There is no multi-layer callback nested in the world, write more people will have.
Using promise to solve the problem of callback hell
What is promise?
Promise is an abstract object. COMMONJS defines the PROMISES/A specification.
If you want to be specific about this: Learn more about what promise is.
Promise mode is in one of the following three states at any time:
Not completed (unfulfilled)
Completed (resolved)
Reject (rejected).
More than 1.5 of the Ajax versions of jquery are based on promise implementations. So we can implement AJAX requests using the following methods:
The code is as follows |
Copy Code |
$.when ( $.ajax (' url '), $.ajax (' Url2 ') ) . then (Successcallback,failcallback); The callback function executes only if 2 Ajax are complete Note: The $.ajax (' URL ') returns a Promise object |
How to implement a promise
Next we're going to implement a promise, and we'll call him deferred (consistent with jquery).
The code is as follows |
Copy Code |
function Deferred () { This.donecallbacks = []; This.failcallbacks = []; } Deferred.prototype.done = function (CB) { This.doneCallbacks.push (CB); return this; }; Deferred.prototype.fail = function (CB) { This.failCallbacks.push (CB); return this; }; Deferred.prototype.resolve = function () { var Dcbs = this.donecallbacks; for (Var i=0,len=dcbs.length;i<len;i++) { Dcbs[i] (); } return this; } The realization of analog $.when function when () { var aidx = 0, Alen=arguments.length, DFD = new Deferred (); function callback () { Console.log ("[+ ++aidx +] method" has been executed); if (Aidx = = ALen) { Dfd.resolve (); Change the execution state of a deferred object } } for (var i=0; i< ALen; i++) { Arguments[i].done (callback); } return DFD; } Customizing methods for asynchronous execution var wait = function (intval) { var DFD = new Deferred (); Inside the function, create a new deferred object var tasks = function () { Console.log ("Time consuming [+intval/1000+] seconds" execution completed!) "); Dfd.resolve (); Change the execution state of a deferred object }; SetTimeout (Tasks,intval); return DFD; Returns the deferred object }; Call Test When (5000), Wait (10000). Done (function () {Console.log (' invoke first Done ');}). Done (function () {Console.log (' invoke second Done ');}; Console.log (' over ') |
As the code above, the principle is: use deferred to save the callback function and state, and so on, after the asynchronous operation is completed, change the state, triggering the corresponding callback function.
Solve some problems of asynchronous programming callback using Primose method
If you want to use the Priomse method to solve the callback nesting problem that asynchronous programming brings,
So we're going to need to encapsulate all of our functions that contain asynchronous operations,
Encapsulated into promise objects, we can use a similar:
$.when (Promise1,promise2,....). Then (...);
Back to the example of the animation mentioned at the beginning, we can do this like this:
code is as follows |
copy code |
function Animate (Dis,time) { var def = $. Deferred (); $ ('. Boll ') animate ({ left:dis+ ' px ' },time, function () { def.resolve (time); }); return def; } $ ('. Boll '). On (' click ', Function () { $.when ( Animate ( 50,1000), animate (120,100), animate (200,500)) . Done (function (DD,TT,KK) { console.log (DD,TT,KK) }) }); |
When the argument must be a Promise object, when (XXX) returns a promise.
So this necessarily increases some of the amount of code we have, but it's worth it for better readability and maintainability.
So promise introduces here, and then there are 2 more articles that will use another 2 ways to solve the callback nesting problems that asynchronous programming brings.