Official dojo 1.6 Tutorial: A Preliminary Study of dojo. Deferred

Source: Internet
Author: User
Tags tojson

 

 

 

By Bryan Forbes

Tiimfei@gmail.com (feijia)

Connection: http://dojotoolkit.org/documentation/tutorials/1.6/deferreds/

Applicable dojo version: 1.6

Difficulty: Moderate

 

In this tutorial, you will learn the basics of using the defer (latency) method of dojo.

With the latency method, you can easily and elegantly process common asynchronous calls in JS programming. We will also explain how to use deferredlist, which can process multiple delayed asynchronous calls at a time.

 

Getting started

 

It sounds like the name of "latency" is quite mysterious. But it is actually a powerful tool that dojo provides for us to process asynchronous calls (such as Ajax. simply put, a deferred object will wait for a period of time before executing the specified call until a specific event or the previous action is completed. Ajax is a common example: After an Ajax request is sent, we need to wait for the server to return the response before calling the processing function. So what the deferred object provides us is the ability to delay an action and wait for an event to happen. In this tutorial, We will combine the content of the Ajax tutorial to explain how to use the deferred object to better manage asynchronous JS programs.

 

Dojo. Deferred

 

The concept of latency is not dojo proprietary.
And other JS frameworks have similar objects and implementations. The commonjs organization also defines a set of standards for this.
), Dojo has implemented the dojo. Deferred object since version 0.3.

The deferred object has three states: "unresolve" during initialization. When the event it is waiting for occurs, it enters the "resolve" state. The third State is the error state, that is, the event did not develop as expected. For example, the server returns an error message, also known as the reject status.

 

After creating a deferred object, we can register a callback function by calling the then method of the object, indicating that the callback function is called when an event waiting for the deferred object occurs (RESOLVE. The then method also accepts the second parameter, which can be used to create an error callback function called when an event fails or an error occurs (reject.

 

Let's take an example:

 

VaR def = new dojo. deferred (), <br/> userlist = dojo. byid ("userlist"); </P> <p> def. then (function (RES) {<br/> // This will be called when the deferred <br/> // is resolved <br/> dojo. foreach (Res, function (User) {<br/> dojo. create ("Li", {<br/> ID: user. ID, <br/> innerhtml: user. username + ":" + User. name <br/>}, userlist); <br/>}); <br/>}, function (ERR) {<br/> // This will be called when the deferred <br/> // is rejected <br/> dojo. create ("Li", {<br/> innerhtml: "error:" + err <br/>}, userlist); <br/> }); </P> <p> dojo. xhrget ({<br/> URL: "users. JSON ", <br/> handleas:" JSON ", <br/> load: function (RES) {<br/> // resolve when content is already ed <br/> def. resolve (RES); <br/>}, <br/> error: function (ERR) {<br/> // reject on error <br/> def. reject (ERR); <br/>}< br/>}); <br/>
 

View examples

 

In the above example, we created a dojo. Deferred object and registered a successful callback function and an error callback function respectively. We also called dojo. xhrget an asynchronous Ajax call to get "user. JSON" from the server ". If this Ajax call is successful, we will use the dojo. if the deferred object is set to resolve, the callback function registered on the deferred object will be called. If Ajax fails to be called, the error callback function registered on deferred will be called.

 

 

In the above example, you may think this is an extra step. Why don't you directly set the Success and Failure callback functions in xhrget? Yes, you can, but by introducing the deffered object, we understand the logic for processing the data returned by the server (callback function) and the logic for sending Ajax requests.

 

In fact, to make it easier for developers to use the deffered object, the Ajax constructor method of dojo will directly return a deferred object to you, so the above Code can be much simpler:

 

VaR def = dojo. xhrget ({<br/> URL: "users. JSON ", <br/> handleas:" JSON "<br/>}); </P> <p> def. then (function (RES) {<br/> var userlist = dojo. byid ("userlist"); </P> <p> dojo. foreach (Res, function (User) {<br/> dojo. create ("Li", {<br/> ID: user. ID, <br/> innerhtml: user. username + ":" + User. name <br/>}, userlist); <br/>}); <br/>}, function (ERR) {<br/> // This shouldn't occur, but it's defined just in case <br/> alert ("an error occurred:" + ERR); <br/>}); <br/>
 

View examples

 

In this example, we no longer need to set the load attribute of dojo. xhrget. You can use then to register the callback function directly on the deferred object returned by xhrget. The Code logic is more intuitive and concise.

 

In the callback function, we traverse the user list returned from the server and create an HTML list for each user. In terms of functionality, it is exactly the same as the previous example, but in this example, we can separate the logic for processing server-side data from the logic for sending Ajax requests. Therefore, an important function of the deferred object is to decouple our program logic. (Decoupling)

 

Chain call

 

Dojo. deferred is an easy-to-understand concept, but it also has some powerful functions that we can continue to explore. one of them is chaining: the return value of each then method is still a defered object. Let's look at an example:

 

In the preceding example, the server does not return a user object in JSON format, but the original value of each user's information. The value is certainly not as easy to use as the object, so we hope to register a callback function to convert these original values into user objects.

VaR original = dojo. xhrget ({<br/> URL: "users-mangled.json", <br/> handleas: "JSON" <br/> }); </P> <p> var result = original. then (function (RES) {<br/> var userlist = dojo. byid ("userlist1"); </P> <p> return dojo. map (Res, function (User) {<br/> dojo. create ("Li", {<br/> innerhtml: dojo. tojson (User) <br/>}, userlist); </P> <p> return {<br/> ID: User [0], <br/> Username: user [1], <br/> name: User [2] <br/>}; <Br/>}); <br/> }); </P> <p> // The result object returned by the then method of original also has a 'then' method to accept the callback function, which is the same as the original object. <Br/> // but note that the value of the callback function registered in result. Then is not the data obtained by Ajax call, but the return value of the original callback function. <Br/> // that is, the user object map that has undergone format conversion <br/> result. then (function (objs) {<br/> var userlist = dojo. byid ("userlist2"); </P> <p> dojo. foreach (objs, function (User) {<br/> dojo. create ("Li", {<br/> innerhtml: dojo. tojson (User) <br/>}, userlist); <br/>}); <br/>

Note: strictly speaking, the return value of the then method is not a deferred object. It has a specific name "Promise", that is, commitment, implementing a specific API. you can read more about prommise.
But here, we can temporarily understand that a promise object provides the same then method as a deferred object. Therefore, the then method of the deferred object and promise object can be continuously chained. What are the benefits of doing so? During a chained call, the original defered object is not modified, and the data returned by the server is not modified, you can continue to register other callback functions on the deinal defered object to perform further operations on the original data. In the previous example, you can register a new callback to original. For example:

Original. then (function (RES) {<br/> var userlist = dojo. byid ("userlist3"); </P> <p> dojo. foreach (Res, function (User) {<br/> dojo. create ("Li", {<br/> innerhtml: dojo. tojson (User) <br/>}, userlist); <br/>}); <br/>
 

 

View examples

 

 

We can further change the above example:

 

Function getuserlist () {<br/> // note that we do not return the data obtained by xhrget, <br/> // but of. then call on that xhrget's return <br/> return dojo. xhrget ({<br/> URL: "users-mangled.json", <br/> handleas: "JSON" <br/> }). then (function (RES) {<br/> return dojo. map (Res, function (User) {<br/> return {<br/> ID: User [0], <br/> Username: User [1], <br/> name: User [2] <br/>}; <br/>}); <br/> }); <br/>}< br/> getuserlist (). then (function (users) {<br/> var userlist = dojo. byid ("userlist"); <br/> dojo. foreach (users, function (User) {<br/> dojo. create ("Li", {<br/> innerhtml: dojo. tojson (User) <br/>}, userlist); <br/>}); <br/>

Through this encapsulation, The getuserlist method can always obtain a list of users that have been processed. (Experiment: Will repeated calls lead to multiple Ajax calls ?)

 

Dojo. deferredlist

 

Sometimes, we need to get data from multiple different sources at the same time. When all the data is in place, we hope to be notified. Dojo also provides convenient encapsulation to help you complete this task. This is the dojo. deferredlist object.

 

When using dojo. deferredlist, you only need to pass a set of deferred objects (as arrays) into its constructor, And it will return a new deferred object to you. On this object, you can register a callback function. When this callback function is called, the results of the original deferred object will be passed into this callback function as parameters. The parameter is a tuple array (tuple is a binary value pair ). The first value in the value pair is a Boolean, indicating whether the deferred is successful or failed, and the second value is the return value of the deferred. Let's take an example:

 

Dojo. require ("dojo. deferredlist "); <br/> dojo. ready (function () {<br/> // The first Ajax request generates a defferred object: userdef <br/> var usersdef = dojo. xhrget ({<br/> URL: "users. JSON ", <br/> handleas:" JSON "<br/> }). then (function (RES) {<br/> var users ={}; <br/> dojo. foreach (Res, function (User) {<br/> Users [user. id] = user; <br/>}); <br/> return users; <br/>}); <br/> // another Ajax request, generate the second defferred object: statusesdef <Br/> var statusesdef = dojo. xhrget ({<br/> URL: "statuses. JSON ", <br/> handleas:" JSON "<br/> }); <br/> // construct a defferredlist object using two defferred objects <br/> var defs = new dojo. deferredlist ([usersdef, statusesdef]); <br/> // The deferredlist object also has a then method used to register the callback function, the callback function parameter is an array composed of tuple <br/> // This callback function is called only when all the deferred objects contained in the current defferredlist enter the resolved or error state. <Br/> defs. then (function (results) {<br/> // The second value of each tuple, which is the return value of the corresponding callback function registered by deferred, <br/> var users = Results [0] [1], <br/> statuses = Results [1] [1], <br/> statuslist = dojo. byid ("statuslist"); <br/> // the first value of each tuple, which is a Boolean, indicates whether the request represented by the deffered object is successful, that is, whether the deffered is successful resolved <br/> If (! Results [0] [0] |! Results [1] [0]) {<br/> dojo. create ("Li", {<br/> innerhtml: "An error occurred" <br/>}, statuslist); <br/> return; <br/>}< br/> dojo. foreach (statuses, function (Status) {<br/> var user = users [status. userid]; <br/> dojo. create ("Li", {<br/> ID: status. ID, <br/> innerhtml: user. name + 'said, "'+ status. status + '"' <br/>}, statuslist); <br/>}); <br/>

 

In this example, we want to obtain user information and user status from the server. We use a deferrredlist to process the two requests after they are completed. The callback function first checks whether both requests are successfully completed. If no error occurs, the user data and status data obtained by the two requests are traversed. The callback function is called only when both requests are completed. Therefore, we do not need to worry about which request is completed first.

 

(Imagine how to manually handle this situation without deferredlist ?)

 

 

View examples

 

Conclusion

 

Most JavaScript applications require Ajax, so they all need to register asynchronous callback functions. Dojo. Deferred provides such a simple and elegant method. It can be very flexible for chained calls, and the use of dojo. deferredlist allows you to process a deferred object.

 

 

 

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.