Describes the role of jQuery's promise object in JavaScript asynchronous programming, jquerypromise

Source: Internet
Author: User

Describes the role of jQuery's promise object in JavaScript asynchronous programming, jquerypromise

Promise, which can be understood as a desire in Chinese, represents the final result of a single operation. A Promise has three statuses: unfulfilled (not satisfied), fulfilled (satisfied), failed (failed), fulfilled status, and failed status. A desire can be changed to a satisfied or failed State. Once a desire is satisfied or failed, its status cannot change. This "unchangeable" feature is very important for a Promise. It can prevent other listeners from abnormal behavior caused by modifying a Promise state listener of Promise. For example, if a listener in the fulfilled status changes the Promise status to failed, the listener in the failed status is triggered. If a listener in the failed status sets the Promise status to fulfilled, then the listener in the fulfilled status will be triggered, which will lead to an endless loop. Another way to understand the features of Promise is to regard Promise as a primative type variable in javascript, which can be passed into the called function, but it cannot be changed by the called function.

Each Promise object has a method: then (fulfilledHandler, errorHandler, progressHandler), used to listen to different States of a Promise. FulfilledHandler is used to listen to fulfilled events, errorHandler is used to listen to failed events, and progressHandler is used to listen to progress events. A Promise does not forcibly implement event listening in the SS state (jQuery's Deferred is an implementation of Promise, but it does not process events in the progress State ).

The returned values of fulfilledHandler and errorHandler in the then (...) function are a new Promise object, so that the then (...) function can be chained. Under normal circumstances, each callback function returns a Promise in the fulfilled State. If the callback function returns an error value, the returned Promise state will change to failed.

Role of promise in asynchronous programming

Asynchronous mode becomes more and more important in web programming. For Javascript, the implementation of this mode is not very beneficial. For this reason, many Javascript libraries (such as jQuery and Dojo) added an abstraction called promise (also called deferred ). With these libraries, developers can use the promise mode in actual programming.
With the development of Web 2.0 technology, the browser end is under more and more computing pressure, so "concurrency" has positive significance. For developers, it is necessary to maintain the interaction between pages and users, and coordinate the relationship between pages and asynchronous tasks. This programming requirement for nonlinear execution is difficult to adapt. Aside from page interaction, we can think of two results for asynchronous calls: successful operations and failure processing. After a successful call, we may need to use the returned results in another Ajax request, which will result in a "function serial set. This situation may cause programming complexity. Take a look at the following code example (based on XMLHttpRequest2 ):

function searchTwitter(term, onload, onerror) {    var xhr, results, url;   url = 'http://search.twitter.com/search.json?rpp=100&q=' + term;   xhr = new XMLHttpRequest();   xhr.open('GET', url, true);    xhr.onload = function (e) {     if (this.status === 200) {       results = JSON.parse(this.responseText);       onload(results);     }   };    xhr.onerror = function (e) {     onerror(e);   };    xhr.send(); }  function handleError(error) {   /* handle the error */ }  function concatResults() {   /* order tweets by date */ }  function loadTweets() {   var container = document.getElementById('container');    searchTwitter('#IE10', function (data1) {     searchTwitter('#IE9', function (data2) {       /* Reshuffle due to date */       var totalResults = concatResults(data1.results, data2.results);       totalResults.forEach(function (tweet) {         var el = document.createElement('li');         el.innerText = tweet.text;         container.appendChild(el);       });     }, handleError);   }, handleError); }

The code above is used to obtain and display the hashtag in Twitter as IE10 and IE9 on the page. This nested callback function is hard to understand. developers need to carefully analyze which code is used for the application's business logic and which code processes asynchronous function calls. The code structure is fragmented. The error handling is also broken down. We need to detect and handle errors in various places.

To reduce the complexity of asynchronous programming, developers have been looking for simple methods to process asynchronous operations. One of the processing modes is called promise, which represents the result of an operation that may run for a long time and may not necessarily have to be complete. This mode does not block or wait for a long time to complete the operation, but returns an object that represents the promised result.

For example, if the Page code needs to access a third-party API, network latency may cause a long response time. In this case, asynchronous programming will not affect the interaction between the whole page and the user. The promise mode usually implements a method called then to register the corresponding callback function when the status changes. For example, the following code example:

searchTwitter(term).then(filterResults).then(displayResults);

Promise mode is in one of the following three States at any time: unfulfilled, resolved, and rejected ). Taking the CommonJS Promise/A standard as an example, the then method on the promise object is responsible for adding processing functions for completed and rejected states. The then method returns another promise object to form a promise pipeline. This method of returning a promise object allows developers to concatenate asynchronous operations, such as then (resolvedHandler, rejectedHandler );. The resolvedHandler callback function is triggered when the promise object enters the completion state and the result is passed. The rejectedHandler function is called in the rejected state.

With the promise mode, we can re-implement the above Twitter example. To better understand the implementation method, we try to build a promise mode framework from scratch. First, you need some objects to store promise.

var Promise = function () {    /* initialize promise */  };

Next, define the then method and accept two parameters for processing completion and rejection.

Promise.prototype.then = function (onResolved, onRejected) {   /* invoke handlers based upon state transition */ };

At the same time, two methods are required to perform the state transition from completed to rejected.

Promise.prototype.resolve = function (value) {   /* move from unfulfilled to resolved */ };  Promise.prototype.reject = function (error) {   /* move from unfulfilled to rejected */ };

Now we have set up a promise shelf. We can continue with the above example, assuming we only get the content of IE10. Create a method to send an Ajax request and encapsulate it in promise. This promise object specifies the transition process of completion and rejection in xhr. onload and xhr. onerror respectively. Note that the searchTwitter function returns the promise object. Then, in loadTweets, use the then method to complete the callback function corresponding to the rejection status.

function searchTwitter(term) {  var url, xhr, results, promise;  url = 'http://search.twitter.com/search.json?rpp=100&q=' + term;  promise = new Promise();  xhr = new XMLHttpRequest();  xhr.open('GET', url, true);  xhr.onload = function (e) {    if (this.status === 200) {      results = JSON.parse(this.responseText);      promise.resolve(results);    }  };  xhr.onerror = function (e) {    promise.reject(e);  };  xhr.send();  return promise;}function loadTweets() {  var container = document.getElementById('container');  searchTwitter('#IE10').then(function (data) {    data.results.forEach(function (tweet) {      var el = document.createElement('li');      el.innerText = tweet.text;      container.appendChild(el);    });  }, handleError);}

So far, we can apply the promise mode to a single Ajax request, which does not seem to reflect the advantages of promise. The following describes the concurrent collaboration of multiple Ajax requests. At this point, we need another method when to store the promise object to be called. Once a promise has never been completed and its status is converted to completed or rejected, the corresponding processing function in the then method will be called. The when method is critical when you need to wait for all operations to be completed.

Promise.when = function () {  /* handle promises arguments and queue each */};

Taking the scenario of obtaining IE10 and IE9 content just now as an example, we can write the code as follows:

var container, promise1, promise2;container = document.getElementById('container');promise1 = searchTwitter('#IE10');promise2 = searchTwitter('#IE9');Promise.when(promise1, promise2).then(function (data1, data2) {  /* Reshuffle due to date */  var totalResults = concatResults(data1.results, data2.results);  totalResults.forEach(function (tweet) {    var el = document.createElement('li');    el.innerText = tweet.text;    container.appendChild(el);  });}, handleError);

The code above shows that the when function will wait for the status of the two promise objects to change and then perform specific processing. In the actual Promise library, the when function has many variants, such as when. some (), when. all (), when. any (), etc., the reader can guess a few points from the function name. For details, refer to a promise in CommonJS to implement when. js.

In addition to CommonJS, other mainstream Javascript frameworks such as jQuery and Dojo all have their own promise implementations. Developers should make good use of this mode to reduce the complexity of asynchronous programming. Let's take Dojo as an example to see how it achieves similarities and differences.

In the Dojo framework, the object implementing the promise mode is Deferred. This object also has the then function used to process the completed and rejected states and supports concatenation, as well as resolve and reject. The function is described earlier. The following code completes the Twitter scenario:

function searchTwitter(term) {  var url, xhr, results, def;  url = 'http://search.twitter.com/search.json?rpp=100&q=' + term;  def = new dojo.Deferred();  xhr = new XMLHttpRequest();  xhr.open('GET', url, true);  xhr.onload = function (e) {    if (this.status === 200) {      results = JSON.parse(this.responseText);      def.resolve(results);    }  };  xhr.onerror = function (e) {    def.reject(e);  };  xhr.send();  return def;}dojo.ready(function () {  var container = dojo.byId('container');  searchTwitter('#IE10').then(function (data) {    data.results.forEach(function (tweet) {      dojo.create('li', {        innerHTML: tweet.text      }, container);    });  });});

In addition, similar to the dojo. xhrGet method, the returned result is the dojo. Deferred object, so you do not have to wrap the promise mode yourself.

var deferred = dojo.xhrGet({  url: "search.json",  handleAs: "json"});deferred.then(function (data) {  /* handle results */}, function (error) {  /* handle error */});

In addition, Dojo also introduces dojo. DeferredList, which allows developers to process multiple dojo. Deferred objects at the same time. This is actually another manifestation of the when method mentioned above.

dojo.require("dojo.DeferredList");dojo.ready(function () {  var container, def1, def2, defs;  container = dojo.byId('container');  def1 = searchTwitter('#IE10');  def2 = searchTwitter('#IE9');  defs = new dojo.DeferredList([def1, def2]);  defs.then(function (data) {    // Handle exceptions    if (!results[0][0] || !results[1][0]) {      dojo.create("li", {        innerHTML: 'an error occurred'      }, container);      return;    }    var totalResults = concatResults(data[0][1].results, data[1][1].results);    totalResults.forEach(function (tweet) {      dojo.create("li", {        innerHTML: tweet.text      }, container);    });  });});

The above code is clear and will not be detailed.

At this point, the reader may have a complete understanding of the promise mode, and asynchronous programming will become increasingly important. In this case, we need to find a way to reduce complexity, the promise mode is a good example. Its style is more user-friendly, and the mainstream JS framework provides its own implementation. In programming practice, developers should try this convenient programming technique. Note that the promise mode needs to be used properly to set the promise object, call the State Conversion Function in the corresponding event, and return the promise object at the end.


Related Article

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.