[Javascript] Promise

Source: Internet
Author: User
Tags event listener

Promise represents an asynchronous operation that is not yet complete, but will be completed in the future.

There are three states of Promise

    • Pending: Initial state, not yet known results
    • Fulfilled: Represents successful operation
    • Rejected: Representative operation failed

If the Promise operation is fulfilled or rejected, and the corresponding handler is declared, the handler function is called.

Promise vs Events Listener (Event listener)

Event listeners are good at handling recurring events on the same object, such as keystrokes, mouse clicks, and so on. For these events, you only care about what happens after you add the callback function. When processing a result-oriented asynchronous event, your code might be

Img1.callthisifloadedorwhenloaded (function() {  //  loaded}). Oriffailedcallthis (function() {  //  failed}); // and ... Whenallthesehaveloaded ([Img1, Img2]). CallThis (function() {  // all Loaded}). Orifsomefailedcallthis (function() {  // one or more failed });

To achieve the same functionality, Promise's code is more concise and more intuitive.

Img1.ready (). Then (function() {  //  loadedfunction() {   //  failed}); // and ... Promise.all ([Img1.ready (), Img2.ready ()]). Then (function() {  // all Loadedfunction() {  // one or more failed});

Promise and event listeners are similar except for the following points

1. Promise only undergoes one execution, success or failure. The Promise is not executed a second time, nor can the execution result be changed, that is, execution fails from success to failure, and vice versa. The event listener can be executed repeatedly.

2. If Promise has completed, succeeded or failed, and then adds the corresponding callback function to Promise, then the corresponding callback function will still be executed. That is, after Promise adds a callback function, the callback function checks to see if the event has occurred before it is added, executes if it occurs, and waits if it does not occur. The event listener is only responsible for events that have been added, ignoring events that were before they were added.

The above two points are very advantageous for handling result-oriented asynchronous events. Because you only need the result of a relationship event, success or failure, without knowing exactly when the event occurred.

Use of Promise

Promise already exist in some libraries, such as

    • Q
    • When
    • WinJS
    • Rsvp.js

Create Promise

Most of the Promise implementations in the class library follow the standard behavior, promises/a+. But the API can be a little different. Javascript comes with a Promise that uses a similar rsvp.js API.

var New Promise (function(resolve, Reject) {  // do a thing, possibly async, then ...  if (/**/) {    resolve ("Stuff worked!") );  }   Else {    reject (Error ("It broke");  });

The Promise constructor takes a callback function as a parameter. The callback function is executed when the Promise object is created. Depending on the result of the callback function, either succeeds or fails, the execution controller is given the reolve () or Reject () function. However, the time reolve () or reject () is being executed after they have been added through Promise.then ().

Using Promise
Promise.then (function(result) {  //  "Stuff worked!" function (Err) {  //  Error: "It Broke"});

Promise.then () accepts two parameters, one for handling Promise execution success, and another for handling Promise failures. Two parameters are optional, so you can just pass the function to the first argument, to handle Promise success, or just pass the function to the second parameter, to handle the Promise failure.

Chained calls (chaining)

Promise.prototype.then () and Promise.prototype.catch () return a Promise, so a chained call can be formed. Chained calls can be used for value passing, or subsequent asynchronous operations in turn.

Value passing
var New Promise (function(resolve, reject) {  Resolve (1);}); Promise.then (function(val) {  ///  1  return val + 2 ;}). Then (function(val) {  //  3});

When then () simply calls another function, you can simply pass the function name of the other function. For example

Get (' Story.json '). Then (function(response) {  return  json.parse (response);}). Then (function(response) {  Console.log ("Yey json!") , response);});

can be simplified to

Get (' Story.json '). Then (Json.parse). Then (function(response) {  Console.log ("Yey json!" , response);});

The actual combat code is as follows

function Getjson (URL) {  return  get (URL). then (json.parse);}

concatenating multiple asynchronous operations

If then returns a value, the next then will accept the value to continue execution. If then returns an object of another Promise, then the next then waits until the returned Promise executes (succeeds or fails).

Getjson (' Story.json '). Then (thefunction(story)  {return Getjson (story.chapterurls[0 ]);}). Then (function(chapter1) {  console.log ("Got Chapter 1!") , Chapter1);});

To send a Story.json request, the result is a story object containing multiple chapter URLs. The JSON data is requested again based on the first chapter URL. After successful execution, the Console.log is run last.

Example

A target resource Story.json is known and needs to be implemented in the following steps

1. Send a request to Story.json to get the URL of each chapter,

2. Send a request to each section URL to obtain the respective chapters

3. Add chapter content to an HTML page

Synchronizing Request data

Because it is a synchronous request, all requests are blocked in turn. The page is also blocked during the request and no other action is taken. This approach allows for data loading, but the user experience is poor.

Try {  var story = Getjsonsync (' Story.json ');  Addhtmltopage (story.heading);  Story.chapterUrls.forEach (function(chapterurl) {    var chapter =  Getjsonsync (chapterurl);    Addhtmltopage (chapter.html);  });  Addtexttopage ("All Done");} Catch (Err) {  addtexttopage ("Argh, Broken:" + err.message);} Document.queryselector ('. Spinner '). Style.display = ' None ';

Promise Asynchronous Request data
Getjson (' Story.json '). Then (function(story) {addhtmltopage (story.heading); //todo:for each URL in Story.chapterurls, Fetch & Display}). Then (function() {  //and we ' re all done!Addtexttopage ("All Done");}).Catch(function(err) {//Catch Any error that happened along theAddtexttopage ("Argh, Broken:" +err.message);}). Then (function() {  //Always hide the spinnerDocument.queryselector ('. Spinner '). Style.display = ' None ';});

Above is a framework code that loads each chapter of the functionality of each implementation. Because the array's foreach function is not an asynchronous operation, it is not possible to simply use foreach to make an asynchronous request for each chapter. You can convert an array to a Promise queue to achieve the traversal effect.

// Start off with a promise this always resolves var sequence = promise.resolve (); // Loop through our chapter URLsStory.chapterUrls.forEach (function(chapterurl) {  //  Add These actionsto the end of the sequence  sequence = Sequence.then (function() {
    return  Getjson (chapterurl);  }). Then (function(chapter) {    addhtmltopage (chapter.html);  });});

or use Array.reduce to achieve

// Loop through our chapter URLsstory.chapterUrls.reduce (function(sequence, chapterurl) {   //  Add These actionsto the end of the sequence  return sequence.then (function
    () {    return  Getjson (chapterurl);  }). Then (function(chapter) {    addhtmltopage (chapter.html);  });}, Promise.resolve ());

Combine the framework code and the code that loads the chapters.

Getjson (' Story.json '). Then (function(story) {addhtmltopage (story.heading); returnStory.chapterUrls.reduce (function(sequence, chapterurl) {//Once the last chapter ' s promise was done ...    returnSequence.then (function() {      //... fetch the next chapter      returnGetjson (Chapterurl); }). Then (function(chapter) {//and add it to the pageaddhtmltopage (chapter.html);  }); }, Promise.resolve ());}). Then (function() {  //and we ' re all done!Addtexttopage ("All Done");}).Catch(function(err) {//Catch Any error that happened along theAddtexttopage ("Argh, Broken:" +err.message);}). Then (function() {  //Always hide the spinnerDocument.queryselector ('. Spinner '). Style.display = ' None ';});

The effect of the implementation is as follows:

Now, you can perform asynchronous, nonblocking loading of data sequentially, and load first. However, this loading method also has the space to optimize.

Promise Optimized version 1

Load the data in parallel, all loaded and displayed at the same time. The effect is as follows

Promise Optimized version 2

Load the data in parallel, showing each of the completed chapters in sequence according to the chapter order. The effect of this loading method is final. When using Chrome, it feels like data is loading quickly, and guessing is the way data is loaded.

The effect is as follows

The last two optimized versions of ideas and code reference JavaScript Promise, Jake Archibald

Resources

Promise-javascript | MDN

JavaScript Promise, Jake Archibald

[Javascript] Promise

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.