JavaScript Promise Revelation _javascript Tips

Source: Internet
Author: User

This article, mainly popularize the usage of promise.

All along, JavaScript processing asynchronous is in the callback way, in the front-end development field callback mechanism almost popular. When designing APIs, both the browser manufacturer and the SDK developer, or the authors of various libraries, have basically followed the callback routines.

In recent years, as the JavaScript development model gradually matured, COMMONJS standard homeopathy, including the proposed promise specification, promise completely changed the JS asynchronous programming, so that asynchronous programming becomes very easy to understand.

In the callback model, we assume that we need to execute an asynchronous queue, and the code might look like this:

Loadimg (' a.jpg ', function () {
  loadimg (' b.jpg ', function () {
    loadimg (' c.jpg '), function () {
      Console.log (' All done! ');});

This is what we often say the callback pyramid, when the asynchronous task is many, the maintenance of a large number of callback will be a disaster. Today Node.js big hot, as if a lot of teams have to use it to do something to dip "brim", once with a yun-dimensional classmate chat, they are also going to use node.js to do something, but a thought of JS layer callback on the daunting.

Okay, all right, let's get down to business.

Promise may not be unfamiliar to everyone, because the promise specification has been out for some time, and promise has been included in the ES6, and the high version of the Chrome, Firefox browser has been native to achieve the promise, It's just less API than the popular class promise Class library today.

The so-called promise, literally can be understood as "commitment", that is, a call b,b returns a "commitment" to a, and then a can write the plan as follows: When B returns the result to me, a executes the scheme S1, whereas if B does not give a desired result for any reason, Then a executes the contingency plan S2, so that all potential risks are within the controllable range of a.

The above sentence is translated into code like this:

var resb = B ();
var Runa = function () {
  resb.then (execS1, execS2);
Runa ();

Just look at this line of code, as if there is nothing special. But the reality can be a lot more complicated than this, a to do one thing, may rely on more than B a person's response, you may need to ask many people at the same time, when all the answers are received and then follow the next step. The final translation into code might look like this:

var resb = B ();
var resc = C ();
...

var Runa = function () {
  reqb
    . Then (Resc, ExecS2). Then (RESD, ExecS3). Then (Rese
    ,
    execS4). C14/>.then (execS1);
};

Runa ();

Here, when each respondent makes a response that does not meet expectations, it uses a different processing mechanism. In fact, the Promise specification does not require that you can even do any processing (that is, not passing in the second parameter of the then) or uniformly.

OK, let's meet the promise/a+ specification below:

    • There may be three states of a promise: Wait (pending), completed (fulfilled), rejected (rejected)
    • A promise state can only be transferred from "Wait" to "complete" or "reject", and cannot be reversed, while the "complete" and "reject" states cannot be converted to each other.
    • Promise must implement the then method (it can be said that then is the core of promise), and then must return a promise, the promise of the same then can be invoked multiple times, and the order of the callbacks is the same as the order in which they are defined.
    • The then method accepts two parameters, the first of which is a successful callback, which is invoked when the promise is converted from "Wait" to the "completed" state, and the other is the callback at the time of failure, which is invoked when promise is converted from "Wait" state to "deny" state. At the same time, then can accept another promise incoming, and also accept a "class then" object or method, that is, thenable object.

You can see that the content of promise norms is not much, we can try to achieve the following promise.

The following is the author's own reference to many types of promise library after a simple implementation of a promise, code please PROMISEA.

Simple analysis of the idea:

Constructor promise accepts a function that resolver can be understood as passing in an asynchronous task, resolver accepts two parameters, one is a successful callback, the other is a callback when it fails, and the two parameters are equivalent to those passed through then.

followed by the implementation of the then, because the promise requirements then must return a promise, so in the then call will be reborn into a promise, hanging on the current promise _next , the same promise multiple calls will only return the previously generated _next.

Since the two parameters accepted by the then method are optional, and the type is not limited, it can be a function, a specific value, or another promise. The following are the specific implementations of then:

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, the then is simplified, the implementation of the other Promise class libraries is much more complex and more functional, such as the third parameter--notify, which represents promise current progress, which is useful when designing file uploads. The processing of various parameters of then is the most complicated part, and interested students can see the implementation of other classes of promise libraries.

On the basis of then, it should also require at least two methods to complete the conversion of promise State from pending to resolved or rejected, while executing the corresponding callback queue, that is, resolve() and the reject() method.

To this end, a simple promise is designed, following the simple implementation of the next two promise functions:

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 an argument, getImg you can also call this:

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 Moment), assuming that there is a demand for BT to do so: get a JSON configuration asynchronously, parse the JSON data to get the inside picture, and then load the picture in order queue, no picture is loaded with a loading effect

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 (())
    . Then (function () {
      $ (' #done '). Show ();

$ (' #run '). On (' click ', run);

The sleep here is only to see the effect Plus, can bash view demo! Of course, the node.js example can be viewed here.

Here, the Promise.resolve(v) static method simply returns a promise,v with a positive result of V, either a function or an then object or function that contains a method (that is, thenable).

A similar static method also Promise.cast(promise) generates a promise with promise as the positive result;

Promise.reject(reason), and generates a promise with reason as the negative result.

Our actual usage scenarios can be complex, often requiring multiple asynchronous tasks to be interleaved, parallel or serial. At this point, you can extend various extensions to the promise, such as implementations Promise.all() , accept promises queues, and wait for them to complete, and then, for example Promise.any() , the next action is triggered when any one of the promises queues is in a complete state.

The standard Promise

Refer to Html5rocks's article JavaScript promises, now advanced browsers such as Chrome, Firefox have built the Promise object, providing more operational interface, for example Promise.all() , to support the introduction of a promises array, When all the promises are done then, there is a more friendly and powerful exception capture that should suffice for routine asynchronous programming.

The promise of the third Third-party

The current popular major JS library, almost all the different degrees of implementation of the promise, such as Dojo,jquery, Zepto, When.js, Q, and so on, but most of the exposed is the Deferred object to JQuery (Zepto similar) as an example, to achieve the above getImg() :

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, many of the operations in jquery are returned by deferred or promise, such animate as 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. ');
  the function () {
    console.error (' There something wrong. ');
  });

jquery is also implemented done() and fail() methods, in fact, are then method of shortcut.

To handle promises queues, jquery implements $.when() methods, usages, and Promise.all() similarities.

Other class libraries, here is worth mentioning is when.js, its own code is not much, complete implementation of promise, while supporting browser and Node.js, and provide a richer API, is a good choice. This is limited to space and no longer unfolds.

End

We see that no matter how complicated the promise implementation is, but its usage is very simple, the organization's code is very clear, and no longer suffer from callback.

In the end, promise is so elegant! But promise also only solves the deep nesting of the callback problem, the real simplification of JavaScript asynchronous programming or generator, on the Node.js side, the proposal to consider generator.

Next, study under generator.

GitHub Original: HTTPS://GITHUB.COM/CHEMDEMO/CHEMDEMO.GITHUB.IO/ISSUES/6

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.