A detailed explanation of deferred object usage in jquery

Source: Internet
Author: User
Tags advantage

It solves the problem of how to handle time-consuming operations, provides better control over those operations, and a unified programming interface. Its main function can be summed up to four points. Here we go through the example code, step-by-step learning.

Second, the Ajax operation of the chain-type wording

First, review the traditional writing of jquery's Ajax operations:

The code is as follows Copy Code

$.ajax ({

URL: "Test.html",

Success:function () {
Alert ("Haha, success!") ");
},

Error:function () {
Alert ("Wrong!") ");
}

});

(Run code example 1)

In the above code, $.AJAX () accepts an object parameter that contains two methods: The Success method specifies the callback function after the operation succeeds, and the error method specifies the callback function after the operation fails.

After the $.ajax () operation is completed, if you are using jquery that is less than 1.5.0, the XHR object is returned and you cannot perform a chain operation; If the version is higher than 1.5.0, the deferred object is returned and can be chained.

Now, the new wording is this:

 

The code is as follows Copy Code

$.ajax ("test.html")

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 2)

As you can see, the done () equivalent to the Success method, fail () is equivalent to the error method. With the chain style, the readability of the code is greatly improved.

Three, specifying multiple callback functions for the same operation

One of the great benefits of deferred objects is that it allows you to add multiple callback functions freely.

Or take the above code as an example, if the Ajax operation succeeded, in addition to the original callback function, I would like to run a callback function, how to do?

It's simple, just add it to the back of the line.

  

The code is as follows Copy Code

$.ajax ("test.html")

. Done (function () {alert ("Haha, success!") ");} )

. Fail (function () {alert ("Error!) "); } )

. Done (function () {alert ("Second callback function!) ");} );

(Run code example 3)

The callback function can add as many as you want, and they are executed in the order of addition.

Specifying callback functions for multiple operations

Another great benefit of the deferred object is that it allows you to specify a callback function for multiple events, which is not possible with traditional writing.

Take a look at the code below, which uses a new method $.when ():

The code is as follows Copy Code

$.when ($.ajax ("test1.html"), $.ajax ("test2.html"))

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 4)

This code means that two operations $.ajax ("test1.html") and $.ajax ("test2.html") are executed first, and if all succeeds, the done () specified callback function is run, and if one fails or fails, the fail () is executed. The specified callback function.

Common Operation callback function interface (upper)

The great advantage of the deferred object is that it extends this set of callback function interfaces from Ajax operations to all operations. That is, any operation----either an AJAX or a local operation, whether asynchronous or synchronous----can use various methods of the deferred object to specify the callback function.

Let's look at a concrete example. Suppose there is a time-consuming operation wait:

The code is as follows Copy Code

var wait = function () {

var tasks = function () {

Alert ("Execution complete!") ");

};

SetTimeout (tasks,5000);

};

We specify a callback function for it, what should we do?

Naturally, you will think that you can use $.when ():

 

The code is as follows Copy Code

$.when (Wait ())

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 5)

However, in this case, the done () method executes immediately and does not function as a callback function. The reason is that the $.when () parameter can only be a deferred object, so wait () must be overwritten:

 

The code is as follows Copy Code

var DTD = $. Deferred (); Create a new Deferred object

var wait = function (DTD) {

var tasks = function () {

Alert ("Execution complete!") ");

Dtd.resolve (); Change the execution state of a deferred object

};

SetTimeout (tasks,5000);

return DTD;

};

Now, the Wait () function returns the deferred object, which can be combined with a chained operation.

 

The code is as follows Copy Code

$.when (Wait (DTD))

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 6)

When the wait () function finishes running, the callback function specified by the done () method is automatically run.

Vi. Deferred.resolve () method and Deferred.reject () method

If you look closely, you will find that there is another place in the wait () function above which I did not explain. Is that what Dtd.resolve () is for?

To be clear about this, a new concept, "State of Execution", will be introduced. jquery stipulates that the deferred object has three execution states----incomplete, completed, and failed. If the execution status is completed (resolved), the deferred object immediately invokes the callback function specified by the done () method, or the callback function specified by the fail () method if the execution state is "failed", and continues waiting if the execution state is "incomplete". or call the callback function specified by the progress () method (added by the jQuery1.7 version).

In the previous part of the Ajax operation, the deferred object automatically changes its execution state based on the return result, but in the wait () function, the execution state must be manually specified by the programmer. Dtd.resolve () means that the execution state of a DTD object is changed from incomplete to completed, triggering the Done () method.

Similarly, there is a deferred.reject () method that triggers the Fail () method by changing the execution state of the DTD object from incomplete to failed.

The code is as follows Copy Code

var DTD = $. Deferred (); Create a new Deferred object

var wait = function (DTD) {

var tasks = function () {

Alert ("Execution complete!") ");

Dtd.reject (); Change the execution state of a deferred object

};

SetTimeout (tasks,5000);

return DTD;

};

$.when (Wait (DTD))

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 7)

Vii. deferred.promise () method

There is still a problem with the above wording. That is, the DTD is a global object, so its execution state can be changed from the outside.

Take a look at the following code:

The code is as follows Copy Code

var DTD = $. Deferred (); Create a new Deferred object

var wait = function (DTD) {

var tasks = function () {

Alert ("Execution complete!") ");

Dtd.resolve (); Change the execution state of a deferred object

};

SetTimeout (tasks,5000);

return DTD;

};

$.when (Wait (DTD))

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

Dtd.resolve ();

(Run code example 8)

I added a line of Dtd.resolve () to the end of the code, which changed the execution state of the DTD object, thus causing the done () method to execute immediately, jumping out of the "Haha, success!" "Prompt box, wait 5 seconds before jumping out" execution completed! Prompt box.

To avoid this, jquery provides the Deferred.promise () method. Its role is to return another deferred object on the original deferred object, which only opens methods unrelated to changing the execution state (such as the Done () method and the Fail () method), shielding the methods associated with changing the execution state (e.g. resolve () Method and The Reject () method) so that the execution state cannot be changed.

Take a look at the following code:

The code is as follows Copy Code

var DTD = $. Deferred (); Create a new Deferred object

var wait = function (DTD) {

var tasks = function () {

Alert ("Execution complete!") ");

Dtd.resolve (); Change the execution state of a deferred object

};

SetTimeout (tasks,5000);

return Dtd.promise (); Returns the Promise Object

};

var d = Wait (DTD); Create a new D object and manipulate the object instead

$.when (d)

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

D.resolve (); At this point, the statement is invalid

(Run code example 9)

In the above code, the Wait () function returns the Promise object. We then bind the callback function above the object, not the original deferred object. The advantage is that you cannot change the execution state of this object, and you can only manipulate the original deferred object if you want to change the state of execution.

However, a better way to do this is to turn the DTD object into an internal object of the wait () function, as Allenm points out.

The code is as follows Copy Code

var wait = function (DTD) {

var DTD = $. Deferred (); Inside the function, create a new deferred object

var tasks = function () {

Alert ("Execution complete!") ");

Dtd.resolve (); Change the execution state of a deferred object

};

SetTimeout (tasks,5000);

return Dtd.promise (); Returns the Promise Object

};

$.when (Wait ())

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 10)

General operation of the callback function interface (in)

Another way to prevent the execution state from being externally altered is to use the constructor $ of the deferred object. Deferred ().

At this point, the wait function remains the same, and we pass it directly into $. Deferred ():

The code is as follows Copy Code

$. Deferred (Wait)

. Done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

(Run code example 11)

jquery stipulates that $. Deferred () can accept a function name (note, is the name of the functions) as an argument, $. The Deferred object generated by Deferred () will be the default argument for this function.

Normal operation of the callback function interface (next)

In addition to the above two methods, we can also deploy the deferred interface directly on the wait object.

 

The code is as follows Copy Code

var DTD = $. Deferred (); Generating deferred objects

var wait = function (DTD) {

var tasks = function () {

Alert ("Execution complete!") ");

Dtd.resolve (); Change the execution state of a deferred object

};

SetTimeout (tasks,5000);

};

Dtd.promise (wait);

Wait.done (function () {alert ("Haha, success!") "); })

. Fail (function () {alert ("Error!) "); });

Wait (DTD);

(Run code example 12)

The key here is the dtd.promise (wait) line, which is the role of deploying the deferred interface on the wait object. It is because of this line that you can invoke the done () and fail () directly above the wait.

X. Summary: Methods of deferred objects

There are a number of ways to deferred objects, and here's a summary:

(1) $. Deferred () generates a Deferred object.

(2) Deferred.done () specifies the callback function when the operation succeeds

(3) Deferred.fail () specifies the callback function when the operation fails

(4) when deferred.promise () has no parameters, a new deferred object is returned, the running state of the object cannot be changed, and when the parameter is accepted, the function is to deploy the deferred interface on the Parameter object.

(5) Deferred.resolve () manually change the running state of the deferred object to "completed", triggering the Done () method immediately.

(6) Deferred.reject () This method is just the opposite of Deferred.resolve (), which immediately triggers the fail () method by changing the running state of the deferred object to "failed" after the call.

(7) $.when () specifies a callback function for multiple operations.

In addition to these methods, the deferred object has two important methods, which are not covered in the tutorials above.

(8) Deferred.then ()

Sometimes for the sake of convenience, you can put the done () and fail () together to write, this is the then () method.

$.when ($.ajax ("/main.php"))

. Then (Successfunc, Failurefunc);

If then () has two parameters, the first parameter is the callback function of the Done () method, and the second parameter is the callback method of the Fail () method. If then () has only one parameter, then it is equivalent to done ().

(9) Deferred.always ()

This method is also used to specify the callback function, and its function is to always execute regardless of whether the call is Deferred.resolve () or Deferred.reject ().

The code is as follows Copy Code

$.ajax ("test.html")

. Always (function () {alert ("Executed!"). ");} );

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.