JavaScript Promise and promise

Source: Internet
Author: User

JavaScript Promise and promise

This article focuses on the usage of promise.

For a long time, JavaScript processing Asynchronization is based on callback, And the callback mechanism in the front-end development field is almost deeply rooted in the hearts of the people. When designing APIs, browser vendors, SDK developers, and authors of various class libraries have basically followed the callback routine.

In recent years, with the gradual maturity of the JavaScript development model, the CommonJS specification has emerged, including the Promise specification, which completely changed the js asynchronous programming syntax, it makes asynchronous programming easy to understand.

In the callback model, we assume that an asynchronous queue needs to be executed, and the code may look like this:

loadImg('a.jpg', function() {  loadImg('b.jpg', function() {    loadImg('c.jpg', function() {      console.log('all done!');    });  });});

This is what we often call the callback pyramid. When there are many asynchronous tasks, maintaining a large number of callback will be a disaster. Today's Node. js is very popular. It seems that many teams have to use it to make things so as to be "foreign". They once chatted with an O & M personnel and they also intend to use Node. js does some things, but the thought of js layer-by-layer callback is discouraged.

Well, let's go to the question below.

Promise may be familiar to everyone, because the Promise specification has been available for some time, and Promise has also been incorporated into ES6. In addition, Promise has been implemented by chrome and firefox browsers in higher versions, it only has fewer APIs than the currently popular class Promise class libraries.

The so-called Promise can be literally understood as A "commitment", that is to say, A calls B, B returns A "commitment" to A, and then A can write it like this when writing A plan: when B returns the result to me, A executes solution S1. If B does not give the result to A for any reason, A executes the emergency solution S2. As A result, all potential risks are within the controllable range of.

The above sentence is translated into code similar:

var resB = B();var runA = function() {  resB.then(execS1, execS2);};runA();

Only look at the above line of code, it seems that nothing special. However, the actual situation may be much more complicated than this. A must complete one task and may depend on the response of more than B people. It may need to ask multiple people at the same time, after receiving all the responses, execute the next step. The final translated code may look like this:

var resB = B();var resC = C();...var runA = function() {  reqB    .then(resC, execS2)    .then(resD, execS3)    .then(resE, execS4)    ...    .then(execS1);};runA();

Here, different processing mechanisms are used when each respondent makes an unexpected response. In fact, the Promise specification does not require this. You can do nothing even (that is, do not input the second parameter of then) or perform unified processing.

Now let's get to know the Promise/A + specification:

  • A promise may have three states: pending, fulfilled, and rejected)
  • The state of a promise can only be changed from "Waiting" to "finished" or "REJECTED", and cannot be reversed. At the same time, the "completed" and "REJECTED" States cannot be converted to each other.
  • Promise must be implementedthenMethod (then is the core of promise), and then must return a promise. The then of the same promise can be called multiple times, and the execution sequence of the callback is the same as that when they are defined.
  • The then method accepts two parameters. The first parameter is the callback upon success. It is called when the promise is switched from the "Waiting" state to the "finished" state, and the other is the callback upon failure, called when the promise is switched from the "wait" state to the "reject" state. At the same time, then can be passed in by another promise, or a then-like object or method, that is, a thenable object.

As you can see, there are not many Promise specifications. You can try to implement the following Promise on your own.

The following is a simple Promise implemented by the author after referring to many Promise-like libraries. Please move the code to promiseA.

Simple analysis:

The constructor Promise accepts a function.resolverIt can be understood as passing in an asynchronous task. resolver accepts two parameters: one is the callback when the task is successful, and the other is the callback when the task fails, these two parameters are equivalent to the parameters passed in through then.

The second is the implementation of then. Because Promise requires then to return a promise, a new promise will be generated when then is called, which is mounted to the current promise_nextThe same promise will only return the previously generated_next.

Because the two parameters accepted by the then method are optional and there are no restrictions on the type, they can be functions, a specific value, or another promise. The specific implementation of then is as follows:

Promise.prototype.then = function(resolve, reject) {  var next = this._next || (this._next = Promise());  var status = this.status;  var x;  if('pending' === status) {    isFn(resolve) && this._resolves.push(resolve);    isFn(reject) && this._rejects.push(reject);    return next;  }  if('resolved' === status) {    if(!isFn(resolve)) {      next.resolve(resolve);    } else {      try {        x = resolve(this.value);        resolveX(next, x);      } catch(e) {        this.reject(e);      }    }    return next;  }  if('rejected' === status) {    if(!isFn(reject)) {      next.reject(reject);    } else {      try {        x = reject(this.reason);        resolveX(next, x);      } catch(e) {        this.reject(e);      }    }    return next;  }};

 

Here, then is simplified. The implementation of other promise class libraries is much more complicated than this one, and there are more functions. For example, there is a third parameter -- Progress y, which indicates the current progress of promise, this is useful when designing file uploads. Processing various then parameters is the most complicated part. If you are interested, you can refer to the implementation of other classes of Promise libraries.

On the basis of then, at least two methods should be required to complete the transformation of promise status from pending to resolved or rejected, and execute the corresponding callback queue, that isresolve()Andreject()Method.

At this point, a simple promise is designed. The following two promise functions are implemented:

function sleep(ms) {  return function(v) {    var p = Promise();    setTimeout(function() {      p.resolve(v);    }, ms);    return p;  };};function getImg(url) {  var p = Promise();  var img = new Image();  img.onload = function() {    p.resolve(this);  };  img.onerror = function(err) {    p.reject(err);  };  img.url = url;  return p;};

Because the Promise constructor accepts an asynchronous task as a parametergetImgIt can also be called as follows:

function getImg(url) {  return Promise(function(resolve, reject) {    var img = new Image();    img.onload = function() {      resolve(this);    };    img.onerror = function(err) {      reject(err);    };    img.url = url;  });};

Next (witness the miracle), let's assume there is a BT requirement to achieve this: asynchronously obtain a json configuration, parse json data to get the picture inside, and then load the image in an ordered queue, the loading effect is provided when no image is loaded.

function addImg(img) {  $('#list').find('> li:last-child').html('').append(img);};function prepend() {  $('<li>')    .html('loading...')    .appendTo($('#list'));};function run() {  $('#done').hide();  getData('map.json')    .then(function(data) {      $('h4').html(data.name);      return data.list.reduce(function(promise, item) {        return promise          .then(prepend)          .then(sleep(1000))          .then(function() {            return getImg(item.url);          })          .then(addImg);      }, Promise.resolve());    })    .then(sleep(300))    .then(function() {      $('#done').show();    });};$('#run').on('click', run);

The sleep here is only added to view the effect. You can click it to view the demo! Of course, the Node. js example can be viewed here.

Here,Promise.resolve(v)The static method simply returns a promise with v as the positive result. v can be either a function orthenMethod object or function (thenable ).

Similar static methods includePromise.cast(promise), Generate a promise with promise as the positive result;

Promise.reject(reason)To generate a promise with the reason as the negative result.

Our actual use scenarios may be very complex. We often need to execute multiple asynchronous tasks in parallel or in serial mode. In this case, you can perform various extensions on Promise, suchPromise.all(), Accept the promises queue and wait for them to finish before continuing, for examplePromise.any(), When any of the promises queues is in the completed state, the next operation is triggered.

Standard Promise

Refer to the html5rocks Article JavaScript Promises. Currently, advanced browsers such as chrome and firefox have built-in Promise objects to provide more operation interfaces, suchPromise.all()You can input a promises array and execute then when all promises are completed. In addition, it is more user-friendly and powerful to capture exceptions. It should be enough to deal with routine asynchronous programming.

Promise of third-party Libraries

Almost all of the popular js libraries have implemented Promise to varying degrees, such as dojo, jQuery, Zepto, when. js, and Q, but most of them are exposed.DeferredObject, using jQuery (similar to Zepto) as an example to implement the abovegetImg():

function getImg(url) {  var def = $.Deferred();  var img = new Image();  img.onload = function() {    def.resolve(this);  };  img.onerror = function(err) {    def.reject(err);  };  img.src = url;  return def.promise();};

Of course, in jQuery, many operations return Deferred or promise, suchanimate,ajax:

// animate$('.box')  .animate({'opacity': 0}, 1000)  .promise()  .then(function() {    console.log('done');  });// ajax$.ajax(options).then(success, fail);$.ajax(options).done(success).fail(fail);// ajax queue$.when($.ajax(options1), $.ajax(options2))  .then(function() {    console.log('all done.');  }, function() {    console.error('There something wrong.');  });

JQuery also implementsdone()Andfail()Method, in fact, is the snapshot cut of the then method.

To process the promises queue, jQuery implements$.when()Method, usage, andPromise.all()Similar.

For other class libraries, it is worth mentioning when. js. The code itself is not much, complete Promise implementation, and support both browser and Node. js, and more abundant APIs are provided, which is a good choice. It is limited to space and will not be expanded.

Conclusion

We can see that no matter how complicated the Promise implementation is, its usage is very simple, the code of the organization is very clear, and there is no need to suffer from callback.

Finally, Promise is so elegant! However, Promise only solves the deep Nesting Problem of callback. To simplify JavaScript asynchronous programming, we recommend that you consider Generator on the Node. js side.

Next, study Generator.

Github: https://github.com/chemdemo/chemdemo.github.io/issues/6


/** What is in javascript?

You are talking about this form:
/**
I am just comment text.
Leave me alone!
*/
You can add multiple lines of text to the two symbols to explain the code for yourself or others to check. /* Indicates the start of the comment. */indicates the end of the comment. The text in the middle does not affect the code execution.

In fact, the multi-line comment is usually in this form:
/* (An asterisk)
I am just comment text.
Leave me alone!
*/
Some may be written:
/** (Two asterisks)
* Comment line 1
* Comment line 2
* Comment line 3
*/
In most cases (except when you need to use tools such as JSDoc to generate API documents), there is no difference between the two methods.

It is worth noting that multi-line comments cannot be nested, and avoid using regular expressions in multi-line comments whenever possible.

I. JAVASCRIPT Solution

Save the following content to an Html file.

<Head>
<Meta http-equiv = "Content-Type" content = "text/html; charset = gb2312"/>
<Title> convert hexadecimal to hexadecimal </title>
</Head>
<Script language = "javascript">
Function SplitStr (SrcStr ){
Var DesStr = "";
Var Str = SrcStr. split ("");
For (I = 0; I <Str. length; I ++ ){
DesStr = DesStr + HexToOcx (Str [I]) + "";
}
Msg. innerText = DesStr;
}
Function HexToOcx (Hex ){
Var x = Hex. substr (0, 1). toUpperCase ();
Var y = Hex. substr (1, 1). toUpperCase ();
Return 16 * GetOcx (x) + GetOcx (y );
}
Function GetOcx (Hex ){
Switch (Hex ){
Case "":
Return 10;
Case "B ":
Return 11;
Case "C ":
Return 12;
Case "D ":
Return 13;
Case "E ":
Return 14;
Case "F ":
Return 15;
Default:
Return parseInt (Hex );
}
}
</Script>
<Body>
<Form id = "form1" name = "form1" method = "post" action = "">
<Textarea name = "src" id = "src"> </textarea> <br/>
<Input type = "button" name = "button1" value = "convert" onclick = "SplitStr (form1.src. value)"/>
</Form>
<Div id = "msg"> </div>
</Body>
</Html>... the remaining full text>

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.