Usage of Promise in JavaScript _ basic knowledge

Source: Internet
Author: User
This article describes how to use Promise in JavaScript. The promise object is an important knowledge point in JS advanced learning. if you need it, you can refer to many languages, to process the asynchronous mode in a more general order, it contains an interesting solution library called promises, deferreds, or futures. JavaScript promises can promote separation of concerns to replace tightly coupled interfaces. This article describes the JavaScript Promises based on the promises/A standard. [Http://wiki.commonjs.org/wiki/Promises/A]

Use case of Promise:

  • Execution rules
  • Multiple remote verification
  • Timeout processing
  • Remote data request
  • Animation
  • Decouples event logic from application logic
  • Eliminate the triangle of callback functions
  • Control parallel asynchronous operations

JavaScript promise is an object that promises to return values in the future. Is a data object with well-defined behaviors. Promise has three possible states:

  1. Pending (TBD)
  2. Rejected (reject)
  3. Resolved (completed)

A rejected or completed commitment has been resolved. A commitment can only be changed from a pending state to a resolved state. Then, the promised state will remain unchanged. It is committed to exist long after the corresponding processing is completed. That is to say, we can obtain the processing result multiple times. We call promise. then () to obtain the result. This function will not be returned until the corresponding processing is committed. We can flexibly establish a bunch of commitments. These concatenated "then" functions should return a new promise or the earliest promise.
With this style, we can write non-synchronous code just like writing synchronous code. It is mainly implemented through combination commitment:

  • Stack tasks: multiple tasks are scattered in the code and correspond to the same promise.
  • Parallel task: multiple promises return the same promise.
  • Serial task: one commitment, and then another commitment.
  • The preceding combinations.

Why is it so troublesome? Can I use only basic callback functions?

Callback function problems

Callback functions are suitable for simple repetitive events, such as making a form valid by clicking, or saving the results of a REST call. The callback function also forms a chain of code. a callback function calls a REST function and sets a new callback function for the REST function. The new callback function then calls another REST function, and so on. The horizontal growth of code is greater than the vertical growth. The callback function looks very simple until we need a result, which is immediately required and will be used in the next row of calculation immediately.

'use strict';var i = 0;function log(data) {console.log('%d %s', ++i, data); }; function validate() {  log("Wait for it ...");  // Sequence of four Long-running async activities  setTimeout(function () {   log('result first');   setTimeout(function () {     log('result second');     setTimeout(function () {      log('result third');      setTimeout(function () {        log('result fourth')      }, 1000);     }, 1000);   }, 1000);  }, 1000); };validate();

I use timeout to simulate asynchronous operations. It is painful to manage exceptions, so it is easy to miss downstream behaviors. When we write callbacks, the code organization becomes messy. It shows that a simulated verification stream can run in NodeJS REPL. In the next section, we will migrate from the pyramid-of-doom mode to a continuous promise.

Figure

'use strict';var i = 0;function log(data) {console.log('%d %s', ++i, data); }; // Asynchronous fn executes a callback result fnfunction async(arg, callBack) {  setTimeout(function(){   log('result ' + arg);   callBack();  }, 1000);}; function validate() {  log("Wait for it ...");  // Sequence of four Long-running async activities  async('first', function () {   async('second',function () {     async('third', function () {      async('fourth', function () {});     });   });  });};validate();

Result of execution in NodeJS REPL

$ node scripts/examp2b.js1 Wait for it ...2 result first3 result second4 result third5 result fourth$

I have encountered an AngularJS dynamic verification scenario where the values of form items are dynamically restricted based on the corresponding table values. The valid value range of a restriction is defined on the REST service.

I wrote a scheduler to operate the function stack based on the request value to avoid callback nesting. The scheduler pops up the function from the stack and executes it. The callback of the function will call the scheduler again at the end until the stack is cleared. Each callback records all verification errors returned from the remote verification call.

I think what I write is an anti-pattern. If I use the promise provided by Angular's $ http call, my thinking will be more linear throughout the verification process, just like Synchronous programming. The flat promise chain is readable. Continue...

Use Promises

The kew promise library is used. Q Library also applies. To use this library, first use npm to import the kew library to NodeJS, and then load the code to NodeJS REPL.

Figure

'use strict';var Q = require('kew');var i = 0; function log(data) {console.log('%d %s', ++i, data); }; // Asynchronous fn returns a promisefunction async(arg) {  var deferred = Q.defer();  setTimeout(function () {    deferred.resolve('result ' + arg);\  }, 1000);  return deferred.promise;}; // Flattened promise chainfunction validate() {  log("Wait for it ...");  async('first').then(function(resp){    log(resp);    return async('second');  })  .then(function(resp){    log(resp);    return async('third')  })  .then(function(resp){    log(resp);    return async('fourth');  })  .then(function(resp){    log(resp);  }).fail(log);};validate();

The output is the same as the nested callback:

$ node scripts/examp2-pflat.js1 Wait for it ...2 result first3 result second4 result third5 result fourth$

The code is a little "long", but I think it is easier to understand and modify. It is easier to add appropriate error handling. Call fail at the end of the chain to capture errors in the chain, but I can also provide a reject processing function in any then for corresponding processing.

Server or browser

Promises is as effective in browsers as in NodeJS servers. The following address, region. All JSFiddle code can be modified. I operate randomly. You can try it several times to get the opposite result. It can be directly extended to multiple promise chains, just like the NodeJS example above.

Parallel Promises

Consider one asynchronous operation to feed another asynchronous operation. Let the latter include three parallel asynchronous behaviors. in turn, feed the last action. Only when all parallel subrequests pass. This was inspired by a dozen MongoDB operations. Some are qualified parallel operations. I implemented the promises flow chart.

How can we simulate parallel promises in the center of the graph? The key is that the largest promise Library has a full function that generates a parent promie containing a group of subpromises. When all sub-promises pass, the parent promise passes. If a child promise rejects the request, the parent promise rejects the request.

Each of the ten parallel promises contains a text promise. The last then method can be completed only when the ten sub-classes pass through or if any sub-classes refuse.

Figure

var promiseVals = ['To ', 'be, ', 'or ',  'not ', 'to ', 'be, ', 'that ',  'is ', 'the ', 'question.']; var startParallelActions = function (){  var promises = [];   // Make an asynchronous action from each literal  promiseVals.forEach(function(value){    promises.push(makeAPromise(value));  });   // Consolidate all promises into a promise of promises  return Q.all(promises);}; startParallelActions ().then( . . .

The following address, region. The complete code is used to check and change the if condition. Run it again until you get an opposite result.

Promise

The promise returned by many APIs has a then function-they are thenable. Generally, I only process the result of the thenable function through then. However, $ q, mpromise, and kew databases have the same APIs for creating, rejecting, or using promise. Here, the API documentation links to the reference section of each database. I usually do not need to construct a promise, except for the unknown descriptions and timeout functions encapsulated by promise in this article. Refer to which promises I created.

Promise Library Interoperability

Most JavaScript promise libraries are interoperable at the then level. You can create a promise from an external promise, because promise can wrap any type of value. Then supports cross-database operations. Except then, other promise functions may be different. If you need a function that is not included in your library, you can package a promise based on your library into a new promise created based on the library that contains the functions you need. For example, JQuery's promise is sometimes criticized. You can package it into Q, $ q, mpromise, or promise of the kew database for operations.

Conclusion

Now I wrote this article, but a year ago I hesitated to embrace promise. I just want to do a job. I don't want to learn new APIs or break my original code (because I misunderstood promise ). I used to think so incorrectly! When I made a little note, it was easy to win a gratifying result.

In this article, I have provided a single promise, promise chain, and a parallel promise example. Promises is not difficult to use. Anyone can use them. To view the complete concept, you can click the reference guide written by an expert. Start with Promises/A's reference and start with the standard JavaScript Promise.

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.