Promise mode __ Algorithm for JavaScript asynchronous programming

Source: Internet
Author: User
Tags advantage

Asynchronous mode is becoming more and more important in web programming, which is not very quick for web-mainstream JavaScript, so many JavaScript libraries (such as jquery and Dojo) add an abstraction called promise (sometimes called a deferred). These libraries allow developers to use the promise pattern in real-world programming. The official IE Blog recently published an article detailing how to use XMLHttpRequest2 to practice the promise model. Let's take a look at the relevant concepts and applications.

Consider an example where a Web page has an asynchronous operation (via XMLHttpRequest2 or WEB workers). With the deepening of Web 2.0 technology, the browser side has been subjected to more and more computational pressure, so "concurrency" has a positive significance. For developers, it is necessary to keep the interaction between the page and the user unaffected, and to coordinate the relationship between the page and the asynchronous task, and the programming requirements of this non-linear execution are difficult to adapt. Without the page interaction, we can think of two kinds of results--successful operations and failure handling--that need to be handled for asynchronous invocations. After a successful call, we may need to use the returned results in another AJAX request, which will result in a "function serial" case (explained in detail in the author's other article, "Nodejs's asynchronous Programming Style"). This situation can result in programming complexity. 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 = =) {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 above code has the function of getting content from Twitter hashtag as IE10 and IE9 and displaying it on the page. This nested callback function is difficult to understand, and developers need to carefully analyze which code is used for the business logic of the application, and which code handles asynchronous function calls, and the code structure is fragmented. Error handling is also broken down, we need to detect the occurrence of errors in various places and make corresponding processing.

To reduce the complexity of asynchronous programming, developers have been looking for easy ways to handle asynchronous operations. One of the processing modes, called promise, represents a result that can run for a long time and does not necessarily have to be a complete operation. Instead of blocking and waiting for a long operation to complete, this pattern returns an object that represents the result of a commitment (promised).

Consider an example where the page code requires access to Third-party APIs, and network latency can result in longer response times, in which case asynchronous programming does not affect the entire page's interaction with the user. The promise pattern typically implements a method called then, which registers the corresponding callback function for state changes. For example, the following code example:

Searchtwitter (term). Then (Filterresults). then (DisplayResults);
The promise mode is in one of the following three states at any time: incomplete (unfulfilled), completed (resolved), and reject (rejected). Taking the Commonjs promise/a standard as an example, the then method on the Promise object is responsible for adding processing functions for the completed and rejected states. The then method returns another promise object to facilitate the formation of the promise pipeline, a way of returning promise objects that enables developers to concatenate asynchronous operations, such as then (Resolvedhandler, Rejectedhandler); The Resolvedhandler callback function fires when the Promise object enters the completion state and the result is passed, and the Rejectedhandler function is invoked in the rejected state.

With the promise model, we can implement the above example of Twitter again. To better understand the implementation approach, we try to build a framework of promise patterns from scratch. First you need some objects to store the promise.

var Promise = function () {/
        * Initialize Promise */
    };

Next, define the then method and accept two parameters to handle the completion and deny status.

Promise.prototype.then = function (onresolved, onrejected) {/
     * Invoke handlers based upon state transition/
 };

At the same time, two methods are required to perform a state transition that has never been completed to completion and has never been completed until rejected.

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

 Promise.prototype.reject = function (Error) {/* move from
     unfulfilled to rejected *
 /};

Now that we've built a promise shelf, we can go on to the example above, assuming that we're just getting IE10 content. Create a method to send an AJAX request and encapsulate it in the promise. This promise object specifies the process of completing and rejecting state transitions in xhr.onload and Xhr.onerror respectively, and note that the Searchtwitter function returns exactly the Promise object. Then, in Loadtweets, use the then method to set the callback function for the completion and deny state.

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 = =) {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 = Documen
            T.createelement (' Li ');
            El.innertext = Tweet.text;
        Container.appendchild (EL);
    });
}, HandleError); }

So far, we can apply the promise pattern to a single Ajax request, and it does not seem to show the promise advantage. Here's a look at concurrent collaboration for multiple AJAX requests. At this point, we need another method when to store the promise object that is ready to be invoked. Once a promise has been converted to a complete or rejected state, the corresponding handler function in the then method is invoked. The When method is critical when you need to wait for all operations to complete.

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

For example, just get IE10 and IE9 two pieces of content, we can write code like this:

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 = con Catresults (Data1.results, data2.results);
    Totalresults.foreach (function (tweet) {
        var el = document.createelement (' li ');
        El.innertext = Tweet.text;
        Container.appendchild (EL);
    });
}, HandleError;

The above code shows that the When function waits for the state of two promise objects to change and then do the specific processing. In the actual promise library, when functions have many variants, such as When.some (), When.all (), When.any (), and so on, the reader can guess some meaning from the function name, Detailed instructions can refer to the commonjs of a promise implementation when.js.

In addition to COMMONJS, other mainstream JavaScript frameworks such as jquery and Dojo have their own promise implementations. Developers should take advantage of this pattern to reduce the complexity of asynchronous programming. Let's take dojo for example and look at the similarities and differences in its implementation.

The object that implements the promise pattern in the Dojo framework is deferred, which also has then functions for processing completion and rejection states and supports concatenation, as well as resolve and reject, as 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 = =) {
            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);});
    }
);

Not only that, a similar Dojo.xhrget method returns the Dojo.deferred object, so there is no need 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 introduced Dojo.deferredlist, which enables developers to handle multiple dojo at the same time. Deferred object, which 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 more clear and no longer detailed.

Speaking here, the reader may have a more complete understanding of the Promise model, asynchronous programming will become more and more important, in this case, we need to find ways to reduce complexity, promise model is a good example, its style is more humane, And the mainstream JS framework provides its own implementation. So in programming practice, developers should try this handy programming technique. It should be noted that the use of the promise pattern requires that the promise object be appropriately set, the state conversion function is invoked in the corresponding event, and the Promise object is returned at the end.

The technical community's focus on asynchronous programming is also heating up, and the domestic community is making its own noises. Senior Technical expert Lao Zhao released a set of open source asynchronous development Auxiliary Library Jscex, its design is ingenious, discard the callback function programming way, adopt a kind of "linear Code, asynchronous execution" thought, interested readers can view here.

Not only the front-end JS library, now the fiery Nodejs platform also appeared many Third-party promise modules, the specific list can be accessed here.

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.