Detailed description of jQuery's deferred object

Source: Internet
Author: User

JQuery is developed quickly. It has a major version every six months and a minor version every two months. (Because it cannot be reproduced, copy the original text. Original article link-Original Author: Ruan Yifeng)

Each version introduces some new features. What I want to introduce today is a new feature introduced from jQuery 1.5.0-the deferred object.

This function is very important and will become the core method of jQuery in the future. It completely changes how to use ajax in jQuery. All ajax code of jQuery has been rewritten to implement it. However, it is abstract, difficult for beginners to master, and there are not many online tutorials. Therefore, I sorted out my study notes, hoping to help you.

This document is not a preliminary tutorial, but intended for developers who already have jQuery experience. If you want to know the basic usage of jQuery, read my jQuery design ideas and jQuery best practices.

==============================================

Detailed description of jQuery's deferred object

1. What is a deferred object?

During website development, we often encounter some javascript operations that take a long time. Both asynchronous operations (for example, ajax reading server data) and synchronous operations (for example, traversing a large array) do not result immediately.

The usual practice is to specify the callback function for them ). Which functions should be called once they are finished.

However, jQuery has very weak functions in callback functions. To change this, the jQuery development team designed the deferred object.

Put simply, the deferred object is jQuery's callback function solution.In English, defer means "delay", so the deferred object means "delay" to a certain point in the future.

It solves the problem of time-consuming operations, provides better control over those operations, and unified programming interfaces. Its main functions can be summarized as four points. Next we will learn through the sample code step by step.

Ii. Link Writing of ajax operations

First, let's review the traditional jQuery ajax operations:

$. Ajax ({

Url: "test.html ",

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

Error: function () {alert ("error! ");}

});

(Run sample code 1)

In the code above, $. ajax () accepts an object parameter. This object contains two methods: The success method specifies the callback function after the operation is successful, and the error method specifies the callback function after the operation fails.

$. After ajax () is completed, if jQuery of version 1.5.0 or earlier is used, the returned XHR object cannot be chained. If jQuery of version 1.5.0 or later is returned, the deferred object is returned, you can perform chained operations.

Now, the new method is as follows:

$. Ajax ("test.html ")

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

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

(Run sample code 2)

As you can see, done () is equivalent to the success method, and fail () is equivalent to the error method. After the code is chained, the code readability is greatly improved.

3. Specify multiple callback functions for the same operation

A major benefit of the deferred object is that it allows you to add multiple callback functions freely.

The above code is used as an example. If I want to run another callback function after the ajax operation is successful, what should I do?

It's easy. Just add it to the back.

$. Ajax ("test.html ")

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

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

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

(Run sample code 3)

Multiple callback functions can be added, which are executed in the order of addition.

4. Specify the callback function for multiple operations

Another major benefit of the deferred object is that it allows you to specify a callback function for multiple events, which is not traditionally written.

See the following code. It uses a new method $. when ():

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

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

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

(Sample code 4)

This Code indicates that two operations are performed first $. ajax ("test1.html") and $. ajax ("test2.html"). If all functions are successful, run the callback function specified by done (). if one or both fails, run fail () the specified callback function.

5. Callback Function interfaces for common operations (I)

The biggest advantage of the deferred object is that it extends this callback function interface from ajax operations to all operations. That is to say, any operation, whether ajax or local, asynchronous or synchronous, can use various methods of the deferred object to specify the callback function.

Let's look at a specific example. Assume that there is a very time-consuming wait operation:

Var wait = function (){

Var tasks = function (){

Alert ("execution completed! ");

};

SetTimeout (tasks, 5000 );

};

What should we do if we specify a callback function for it?

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

$. When (wait ())

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

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

(Run sample code 5)

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

Var dtd = $. Deferred (); // create a new deferred object

Var wait = function (dtd ){

Var tasks = function (){

Alert ("execution completed! ");

      Dtd. resolve ();// Change the execution status of the deferred object

};

SetTimeout (tasks, 5000 );

    Return dtd;

};

Now, the wait () function returns the deferred object, which can be added with a chain operation.

$. When (wait (dtd ))

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

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

(Run code example 6)

After the wait () function is run, the callback function specified by the done () method is automatically run.

6. deferred. resolve () method and deferred. reject () method

If you look at it carefully, you will find that there is another area in the above wait () function that I have not explained. What is the role of dtd. resolve?

To clarify this problem, we need to introduce a new concept "execution status ". JQuery requires that the deferred object has three execution states: incomplete, completed, and failed. If the execution status is "completed" (resolved), the deferred object immediately calls the callback function specified by the done () method. If the execution status is "failed", call fail () the callback function specified by the method. If the execution status is "incomplete", the system continues to wait, or calls the callback function specified by the progress () method (added in jQuery1.7 ).

In the preceding ajax operations, the deferred object automatically changes its execution status based on the returned results. However, in the wait () function, the execution status must be manually specified by the programmer. Dtd. resolve () indicates that the done () method is triggered by changing the execution status of the dtd object from "unfinished" to "completed.

Similarly, a deferred. reject () method also exists to change the execution status of the dtd object from "incomplete" to "failed", thus triggering the fail () method.

Var dtd = $. Deferred (); // create a new Deferred object

Var wait = function (dtd ){

Var tasks = function (){

Alert ("execution completed! ");

      Dtd. reject (); // Changes the execution status of the Deferred object.

};

SetTimeout (tasks, 5000 );

Return dtd;

};

$. When (wait (dtd ))

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

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

(Run sample code 7)

7. deferred. promise () method

There is still a problem with the above method. That is, dtd is a global object, so its execution status can be changed from the external.

See the following code:

Var dtd = $. Deferred (); // create a new Deferred object

Var wait = function (dtd ){

Var tasks = function (){

Alert ("execution completed! ");

Dtd. resolve (); // Changes the execution status of the Deferred object

};

SetTimeout (tasks, 5000 );

Return dtd;

};

$. When (wait (dtd ))

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

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

  Dtd. resolve ();

(Run sample code 8)

I added a line of dtd. resolve () at the end of the Code, which changed the execution status of the dtd object. As a result, the done () method was executed immediately and jumped out of "Haha, succeeded! "Prompt box, wait 5 seconds and then jump out." The execution is complete! "Prompt box.

To avoid this, jQuery provides the deferred. promise () method. The function is to return another deferred object on the original deferred object, which only opens Methods unrelated to the change of execution status (such as the done () method and fail () method ), shielding methods (such as the resolve () method and reject () method) related to changing the execution status so that the execution status cannot be changed.

See the following code:

Var dtd = $. Deferred (); // create a new Deferred object

Var wait = function (dtd ){

Var tasks = function (){

Alert ("execution completed! ");

Dtd. resolve (); // Changes the execution status of the Deferred object

};
SetTimeout (tasks, 5000 );

    Return dtd. promise (); // return the promise object

};

  Var d = wait (dtd); // create a new d object and perform operations on this object.

$. When (d)

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

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

  D. resolve (); // at this time, this statement is invalid

(Run code example 9)

In the above Code, the wait () function returns the promise object. Then, we bind the callback function to this object instead of the original deferred object. The advantage is that the execution status of this object cannot be changed. To change the execution status, you can only operate on the original deferred object.

However, a better way is to change the dtd object to the internal object of the wait () function, as stated by allenm.

Var wait = function (dtd ){

    Var dtd = $. Deferred (); // inside the function, create a new Deferred object.

Var tasks = function (){

Alert ("execution completed! ");

Dtd. resolve (); // Changes the execution status of the Deferred object

};
SetTimeout (tasks, 5000 );

Return dtd. promise (); // return the promise object

};

  $. When (wait ())

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

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

(Run sample code 10)

8. callback function interface for common operations (medium)

Another method to prevent external changes in execution status is to use the deferred Object Construction Function $. Deferred ().

At this time, the wait function remains unchanged, and we pass it directly to $. Deferred ():

  $. Deferred (wait)

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

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

(Run sample code 11)

JQuery rules, $. deferred () can accept a function name (Note: The function name) as the parameter, $. the Deferred object generated by deferred () is used as the default parameter of this function.

9. Callback Function interfaces for common operations (below)

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

Var dtd = $. Deferred (); // generate a Deferred object

Var wait = function (dtd ){

Var tasks = function (){

Alert ("execution completed! ");

Dtd. resolve (); // Changes the execution status of the Deferred object

};

SetTimeout (tasks, 5000 );

};

  Dtd. promise (wait );

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

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

Wait (dtd );

(Run sample code 12)

The key here is the dtd. promise (wait) line. Its function is to deploy the Deferred interface on the wait object. Only with this line can done () and fail () be called directly on wait ().

10. Conclusion: deferred object Method

We have discussed several methods for the deferred object. The following is a summary:

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

(2) deferred. done () specifies the callback function when the operation is successful.

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

(4) deferred. when promise () does not have a parameter, a new deferred object is returned, and its running status cannot be changed. When a parameter is accepted, the deferred interface is deployed on the parameter object.

(5) deferred. resolve () manually changes the running status of the deferred object to "completed", and immediately triggers the done () method.

(6) deferred. reject () This method is similar to deferred. the opposite is true for resolve (). After the call, the running status of the deferred object is changed to "failed", and the fail () method is triggered immediately.

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

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

(8) deferred. then ()

Sometimes, you can combine done () and fail () to save trouble. 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, it is equivalent to done ().

(9) deferred. always ()

This method is also used to specify the callback function. Its function is to always execute whether deferred. resolve () or deferred. reject () is called.

$. 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.