The promise of jquery and the role of deferred objects in asynchronous callbacks _jquery

Source: Internet
Author: User

First, the preface

In order to get the front end back to heaven from the hell of the callback, JQuery also introduced the concept of Promise. Promise is an abstraction that makes code asynchronous behavior more elegant, and with it we can write asynchronous code like write synchronization code. JQuery began with the 1.5 version of the COMMONJS promise/a specification of the heavyweight program, but not strictly follow the specifications to implement, there are some differences in the API.

OK, let's take a look at their features (this example is based on jquery 1.8 version).

Second, the example

We used to do this when we were writing animations:

$ ('. Animateele '). Animate ({
 opacity: '. 5 '
}, 4000,function () {
 $ ('. AnimateEle2 '). Animate ({
  width: ') 100px '
 },2000,function () {
  //This hurts
  $ ('. AnimateEle3 '). Animate ({
   height: ' 0 '
  },2000);
 }
);

It would be too bad if you use a callback like that. Fortunately, there are ready-made Promise solutions to gracefully address this problem.

Let's look at the solution that JQuery offers.

var animate1 = function () {return
 $ ('. AnimateEle1 '). Animate ({opacity: '. 5 '},4000). Promise ();
var animate2 = function () {return
 $ ('. AnimateEle2 '). Animate ({width: ' 100px '},2000). Promise ();
var animate3 = function () {return
 $ ('. AnimateEle3 '). Animate ({height: ' 0 '},2000). Promise ();
So easy, there are wood, so clear, there are wooden
$.when (Animate1 ()). Then (Animate2). then (Animate3);

Obviously, the changed code is easier to read.

However, the above code, some details of the things did not disclose, accidentally, it is easy to make mistakes, do not get the order we want to complete the animation effect. Let's take a complete look at the promise and deferred objects provided by JQuery to see how to use them.

Three, Promise and Deffered object methods

The Promise object is actually a special case of the deferred object because the Promise object cannot change the asynchronous state, and the deferred object can. This is evident in their approach design.

1.promise Object method

In general, we can use the Promise method for DOM, animation, Ajax-related methods. The Promise method is invoked, and the Promise object is returned. You can call the Promise method in a chained style.

There are three common methods for promise objects: done, fail, then.

The other way is not to remember, jquery here the interface method is too much, in my opinion is very verbose, as in the early event method binding, Live, delegate, bind, and ultimately not all belong to on the tube.

code example, as follows:

(1) Dom uses the Promise method:

var box=$ (' #box ');
Box.promise () Done (function (ele) {
  console.log (ele);//jquery box
});

(2) Ajax uses the Promise method (the default returns a Promise object, so you do not have to explicitly invoke the Promise method):

$.post ('/', {}). Done (function (data) {
  Console.log (' request succeeded ');
}. Fail (function () {
  console.log (' request error ');
});

The animation samples are already available and are not listed repeatedly.

2.deferred Object method

So what's the difference between deferred and promise? As you can see earlier, a promise is an object returned by an asynchronous function. When you want to write one of these functions yourself, you need to use a deferred.

A deferred object can do almost as much as a promise object, but it has two functions to trigger the done () and fail () functions.

A deferred object has a resolve () function to handle a successful result and perform a function related to the done (). The Reject () function is used to process failed results and perform functions related to fail ().

You can provide parameters for both the resolve () and The Reject () functions, and they will all be passed to the callback function associated with the done () and fail ().

The Promise object does not have the resolve () and reject () functions. This is because you put promise into other scripts and you don't want to promise to resolve or reject a promise.

Here is a simple example of deferred. HTML is simply an empty div with an id attribute of "result".

$ (' #result '). html (' Waiting ... ');

var promise = Wait ();
Promise.done (result);

function result () {
 $ (' #result '). html (' done ');

function Wait () {
 var deferred = $. Deferred ();

 settimeout (function () {
  deferred.resolve ();
 }, Watts);

 return Deferred.promise ();
}  

where the Wait () function returns a promise. It will be parsed after 2s. In addition to settimeout, everything in an asynchronous function can be used in this way, such as animation, Web worker, and so on. The code in the Wait () function should be clear, we used the deferred object, but we returned a restricted Promise object.

For deferred objects, that is, the use of $. Deferred () method, and $.when () and other methods to create objects, like the following common methods:

Resolve, Reject, notify;
Done, fail, progress;

In addition, there are promise, then and always methods.

The reason for this layout is that they are corresponding, that is to say: The Resolve method triggers the done callback execution, reject triggers the fail callback, and notify triggers the progress callback.

Look directly at the code:

var wait = function (ms) {
 var DTD = $. Deferred ();
 SetTimeout (Dtd.resolve, MS);
 SetTimeout (Dtd.reject, MS);
 SetTimeout (dtd.notify, MS);
 return Dtd.promise (); The DTD can also be returned directly here
;

Wait (2500). Done (function () {
 console.log (' Haha, teacher, you can keep rite waiting ');
}. Fail (function () {
 console.log (' failed ');
}). Progress (function (res) {
 console.log (' Wait ... ');
});

We see that the above code, in the Wait function, returns a Promise object, not a deferred object.

You know, promise objects are not resolve, reject, notify, and so on, meaning that you cannot make state changes to promise objects, only in the done or fail callback configuration. So, if you call Wait (2500). Resolve () will make an error, because wait (2500) Returns a Promise object and there is no resolve method.

However, to do so, there is a benefit, we put the DTD this deferred object in the Wai T function, as a local variable, to avoid global pollution; Further through the promise method, the deferred object of DTD is transformed into promise object, which avoids the function w AIT external possible state changes (if we do have this requirement).

Like what:

var wait = function (ms) {
 var DTD = $. Deferred ();
 SetTimeout (Dtd.resolve, MS);
 SetTimeout (Dtd.reject, MS);
 SetTimeout (dtd.notify, MS);
 return DTD; The DTD can also be returned directly here
;

Wait (2500). Reject (). Fail (function () {
 console.log (' failed ... ');;
});

We changed the state of the deferred object returned by wait externally, which necessarily triggers the object's fail callback function.

For the Always method, it is literally easy to understand that the deferred object, whether resolve or reject, triggers a callback to the method.

3. Other commonalities

Here we talk about the use of then and $.when methods. They also apply to promise objects.

The $.when method accepts multiple deferred objects or pure JavaScript objects, returning promise objects.
The then method accepts three callbacks in turn, the deferred object resolve, reject, the callback triggered after notify, and returns a Promise object. Note that the function must be passed in, and the function can only return a Promise object to allow asynchronous events to execute in the order expected.
Let's take a look at the first animation sample code, $.when (Animate1 ()). Then (Animate2). Then (Animate3), the $.when method accepts a animate1 function execution result, which is a promise Object, then the then only accepts a variable name, which results in an anonymous function body that returns a Promise object. Exactly meets our requirements for then to accept parameters.

If we change the execution statement to: $.when (Animate1 ()). Then (Animate2 ()). Then (Animate3 ()), the result is that three animations are executed synchronously. The same as $.when (Animate1 (), Animate2 (), Animate3 ()).

Since then is so demanding, then the then method similar to the done, fail, progress is the same.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.