Use the code of the deferred object in jQuery 1.5)

Source: Internet
Author: User

Note:
1.DeferredJQuery1.5 is a new feature. Many people translate it into "Asynchronous queue". I think it is reliable. After all, it has nothing to do with "latency, however, I still use the word deferred in this article.

2.This article mentioned in the jQuery1.5 blog that it is also a classic and in-depth article about deferred. In view of the small amount of Chinese materials, it is specially translated for your reference.

3.This article uses the free translation method. If you have any mistakes, please submit them.

JQuery1.5The new Deferreds object in can decouple the processing method of the task completion with the task itself. This is nothing new in the JavaScript community, because the Mochikit and Dojo JS frameworks have implemented this feature for a long time. HoweverJulian AubourgDeferreds naturally becomes the internal implementation logic for rewriting the AJAX module in jQuery1.5. With the deferreds object, multiple callback functions can be bound for execution when the task is completed, or even after the task is completed, these callback functions can be bound. These tasks can be asynchronous or synchronous.

More importantly, deferreds has been used as an internal implementation of $. ajax (), so you can automatically retrieve the traversal brought by deferreds when calling AJAX. For example, we can bind the callback function as follows:
Copy codeThe Code is as follows:
// $. Get, asynchronous AJAX request
Var req = pai.get('foo.htm'). success (function (response ){
// Processing function after AJAX is successful
}). Error (function (){
// Post-processing function for AJAX failure
});
// This function may be called before AJAX ends.
DoSomethingAwesome ();
// Add another AJAX callback function. At this time, AJAX may have ended or may not have ended.
// Because $. ajax has built-in support for deferred, we can write
Req. success (function (response ){
// This function will be called after AJAX ends, or immediately called if AJAX ends.
});

We are no longer limited to only one successful, failed, or completed callback function. On the contrary, these added callback functions are placed in an FIFO queue.
The preceding example shows that the callback function can be attached to an AJAX request (any observed task observable task), or even the AJAX request has ended. The code is well organized and we no longer need to write a long callback function. This is like $. queue () Encountering pub/sub (the publishing and subscription mechanism is generally used in an event-based model ).
More deeply, imagine a scenario where a callback function is executed after all the concurrent AJAX requests are completed. I can easily use the jQuery function $. when () to complete:
Copy codeThe Code is as follows:
Function doAjax (){
Return pai.get('foo.htm ');
}

Function doMoreAjax (){
Return ).get('bar.htm ');
}

$. When (doAjax (), doMoreAjax (). then (function (){
Console. log ('I fire once BOTH ajax requests have completed! ');
}). Fail (function (){
Console. log ('I fire if one or more requests failed .');
});

In jsFiddleOpen example

The preceding example works properly, thanks to the fact that each AJAX method of jQuery contains a promise function to track asynchronous requests.The Return Value of the Promise function is a read-only view of the deferred object. (The promise is a read-only view into the result of the task.)Deferreds checks whether the current object can be observed by checking whether the promise () function exists in the object. $. When () will wait for all AJAX requests to end, and then the call passes. then (),. the callback function registered by fail () (which callback functions are called depends on the end of the task ). These callback functions are executed in their registration order.

Better yet, $. when () accepts an array of functions or functions as a parameter. when accepts one or more deferred objects, or native JS objects. Note that the Function Array cannot be used as the parameter), so that you can freely combine these asynchronous tasks.

$. Ajax ()Returns an object associated with some deferred functions, suchPromise (), then (), success (), error (). However, you cannot operate on the original deferred object. Only the promise () function (Note: Remember that the promise just mentioned is a read-only view) and the isRejected () that can detect the deferred state () and isResolved () functions.

But why not return the deferred object? If a complete deferred object is returned, we have more control and may be able to trigger it at will, is to trigger all the callback functions registered to the deferred object), so that all the callback functions are executed before the end of the AJAX request.Therefore, to avoid the unexpected risk of triggering deferred, we should only return dfd. promise ().(Therefore, to avoid potentially breaking the whole paradigm, only return the dfd. promise ().)
Registering Callbacks)
In the above example, we use the then (), success (), fail () Methods to register callback functions. In fact, there are more methods available, especially when processing AJAX requests. The specific method depends on your attention to the result status.
All functions of a deferred object (AJAX, $. when, or a manually created deferred object ):
Copy codeThe Code is as follows:
. Then (doneCallbacks, failedCallbacks)
. Done (doneCallbacks)
. Fail (failCallbacks)

The AJAX object contains three additional methods, two of which are mapped to the method mentioned above. These methods are designed to be compatible with previous code:
Copy codeThe Code is as follows:
// "Success" and "error" are mapped to the "done" and "fail" methods respectively.
. Success (doneCallbacks)
. Error (failCallbacks)

You can also register a complete callback function, which will be called after the request ends, regardless of whether the request is successful or failed. Unlike the success or error function, the complete function is actually a separate done function alias of the deferred object. This deferred object created inside $. ajax () triggers the callback function (resolve) after AJAX ends ).
Copy codeThe Code is as follows:
. Complete (completeCallbacks)

Therefore, the three examples below are equivalent (in the context of AJAX, success looks more comfortable than the done function, right ?) (Note: In fact, we are familiar with the previous AJAX call methods, which are preemptible or mindset ):
Copy codeThe Code is as follows:
$. Get ("/foo/"). done (fn );
// Equivalent:
$. Get ("/foo/"). success (fn );
// Equivalent:
$. Get ("/foo/", fn );

Create your own deferred object (Creating your own Deferred)
We know that $. ajax and $. when implement the deferred interface internally, but we can also manually create a deferred object:
Copy codeThe Code is as follows:
Function getData (){
Return $. get ('/foo /');
}
Function showDiv (){
Var dfd = $. Deferred ();
$ ('# Foo'). fadeIn (1000, dfd. resolve );
Return dfd. promise ();
}
$. When (getData (), showDiv (). then (function (ajaxResult ){
Console. log ('the animation AND The AJAX request are both done! ');
// 'Ajaxresult' is returned by the server (note: the AJAX result in getData)
});

In jsFiddleOpen example
In showDiv (), we create a deferred object, execute an animation, and return promise. This deferred object will be triggered (resolved) after fadeIn () ends ). In this promise return and deferred object (Note: The deferred here refers to $. A then () callback function is registered between the objects created by when instead of the objects returned by showDiv. This callback function will be executed after all two asynchronous tasks are completed.
GetData () returns an object (the object is actually the XMLHttpRequest object encapsulated by jQuery) with the promise method, which allows $. when () to monitor the end of this AJAX request. The manually steps we took to return a promise in showDiv () is handled for us internally by $. ajax () and $. when ().
1/15/2011: Julian pointed out in the comment that the above syntax can be simplified to $. Deferred (fn). promise (). Therefore, the code at both ends is equivalent:
Copy codeThe Code is as follows:
Function showDiv (){
Var dfd = $. Deferred ();
$ ('# Foo'). fadeIn (1000, dfd. resolve );
Return dfd. promise ();
}
// Equivalent:
Function showDiv (){
Return $. Deferred (function (dfd ){
$ ('# Foo'). fadeIn (1000, dfd. resolve );
}). Promise ();
}

Add a callback function for a custom deferred object (Defer your Deferreds)
We can further register the callback function for getData () and showDiv () respectively, just as we registered the callback function in $. then. (Note: The content in the following paragraphs is repeated and all of them mean one thing. I will not translate them. Check the code)
Copy codeThe Code is as follows:
Function getData (){
Return $. get ('/foo/'). success (function (){
Console. log ('fires after the AJAX request succeeds ');
});
}
Function showDiv (){
Return $. Deferred (function (dfd ){
// Note: This Code does not exist in the original text, but it appears in jsFiddle.
// I think this is the original intent of the author. register the callback function for the custom deferred function.
Dfd. done (function (){
Console. log ('fires after the animation succeeds ');
});
$ ('# Foo'). fadeIn (1000, dfd. resolve );
}). Promise ();
}
$. When (getData (), showDiv (). then (function (ajaxResult ){
Console. log ('fires after BOTH showDiv () AND the AJAX request succeed! ');
// 'Ajaxresult' is the result returned by the server.
});

In jsFiddleOpen example
Chaining Hotness)
The Deferred callback function can be called in a chain, as long as the function returns a deferred object (the Translator's note: dfd. promise () returns a read-only deferred object ). This is an actual code (via @ ajpiano !)
Copy codeThe Code is as follows:
Function saveContact (row ){
Var form = $. tmpl (templates ["contact-form"]),
Valid = true,
Messages = [],
Dfd = $. Deferred ();
/*
* The client verification code is used here.
*/
If (! Valid ){
Dfd. resolve ({
Success: false,
Errors: messages
});
} Else {
Form. ajaxSubmit ({
DataType: "json ",
Success: dfd. resolve,
Error: dfd. reject
});
}
Return dfd. promise ();
};
SaveContact (row). then (function (response ){
If (response. success ){
// The client passes the verification and the data is successfully saved.
} Else {
// Client Verification Failed
// Output error message
}
}). Fail (function (err ){
// AJAX request failed
});

The saveContact () function first verifies the validity of the form data, and then stores the validity state in the variable valid. If the verification fails, the direct deferred will be triggered (passing a JS object containing the success status code and error message as a parameter to the callback function ). If the verification succeeds, data is submitted to the server, and the deferred object is triggered after AJAX is successful. Fail () processes HTTP status codes such as 404,500 that can block the successful completion of AJAX requests.
Non-observable Tasks)
Deferreds is useful for decoupling tasks and task processing functions, regardless of asynchronous tasks or synchronization tasks. A task may return promise, but can also return strings, objects, or other types.
In this example, when the "Lanch Application" link is clicked for the first time, an AJAX request is sent to the server and the current timestamp is returned. The timestamp is then saved to the data cache of the link. When this link is clicked again, it simply retrieves the timestamp from the cache and returns it without sending an AJAX request.
Copy codeThe Code is as follows:
Function startTask (element ){
Var timestamp = $. data (element, 'timestamp ');
If (timestamp ){
Return timestamp;
} Else {
Return $. get ('/start-task/'). success (function (timestamp ){
$. Data (element, 'timestamp', timestamp );
});
}
}
$ ('# LaunchApplication'). bind ('click', function (event ){
Event. preventDefault ();
$. When (startTask (this). done (function (timestamp ){
('{Status'{.html ('<p> You first started this task on:' + timestamp + '</p> ');
});
LoadApplication ();
});

When $. when () finds that its first parameter does not have the promise function (so it cannot be observed), it will create a new deferred object, trigger the deferred object, and return the promise read-only object. Therefore, any unobserved task can be passed to $. when.
Note that if an object itself has a promise function, this object cannot be used as a deferred object. JQuery determines whether an object is deferred by checking whether it has a promise function. However, jQuery does not check whether the promise actually returns an available object. Therefore, the following code will fail:
Copy codeThe Code is as follows:
Var obj = {
Promise: function (){
// Do something
}
};
$. When (obj). then (fn );

Conclusion)
Deferreds proposes a new robust method to process asynchronous tasks. Unlike the traditional method of organizing code into a callback function, the new deferred object allows us to bind multiple callback functions at any time (or even after the task ends, these callback functions are called in the FIFO mode. The information in this article may be hard to digest. However, once you have mastered the use of the deferred object, you will find it very easy to organize the code to be executed asynchronously.
This article was originally published on sanshenshi and first launched in the blog Park. Please indicate the source for reprinting.

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.