Understanding how to use Promise in JavaScript-javascript tutorial

Source: Internet
Author: User
This article mainly introduces the use of Promise in JavaScript. This article first introduces the relevant Promises specifications, and then explains a mini Promises to deepen understanding, interested friends can refer to the Javascript callback function (callback) to process asynchronous programming. From Synchronous Programming to asynchronous callback programming, there is an adaptive process, but if there is multi-layer callback nesting, that is, we often say the bad luck callback Pyramid (Pyramid of Doom ), it is definitely a bad programming experience. Therefore, the Promises/A specification of CommonJS is used to solve the callback pyramid problem. This article first introduces the relevant Promises specifications, and then explains a mini Promises to deepen understanding.

What is Promise?
A Promise object represents a value that is currently unavailable but can be parsed at a certain time point in the future. It allows you to write asynchronous code in synchronous mode. For example, if you want to use the Promise API to call a remote server asynchronously, you need to create a Promise object that will be returned by the Web service in the future. The only problem is that the data is currently unavailable. When the request is completed and the data returned from the server becomes available data. During this period, the Promise object will assume a proxy role for real data. Next, you can bind a callback function to the Promise object. Once real data becomes available, this callback function will be called.

Promise objects have existed in many languages in various forms.

Remove the bad luck callback Pyramid (Pyramid of Doom)
The most common anti-pattern in Javascript is internal callback and nested callback.

// Callback pyramid asyncOperation (function (data) {// process 'data' anotherAsync (function (data2) {// process 'data2 'yetAnotherAsync (function () {// completed });});});

Code after Promises is introduced

PromiseSomething (). then (function (data) {// process 'data' return anotherAsync ();}). then (function (data2) {// process 'data2 'return yetAnotherAsync ();}). then (function () {// complete });

Promises transforms nested callback into a series of. then concatenation calls, removing the bad code style of indentation layer by layer. Promises is not an algorithm for solving specific problems, but a better code organization mode. While accepting the new organization model, we gradually understand asynchronous calls from a new perspective.

Various language platforms have corresponding Promise implementations

  • Java's java. util. concurrent. Future
  • Python's Twisted deferreds and PEP-3148 ures
  • F #'s Async
  • . Net's Task
  • C ++ 11's std: future
  • Dart's Future
  • Javascript's Promises/A/B/D/A +

I believe that I will take a look at the details of various standards in the javascript language environment.

Promises/A Specification
Promise indicates a final value, which is returned when an operation is completed.

  • Promise has three statuses: ** unfulfilled **, ** completed **, and ** failed ).
  • The status of promise can only be converted from ** not completed ** to ** completed **, or ** not completed ** to ** failed **.
  • The promise status conversion only occurs once.

Promise has a then method, which can take three functions as parameters. The first two functions correspond to the callback functions of the two States fulfilled and rejected of promise. The third function is used to process progress information (the support for progress callback is optional ).

PromiseSomething (). then (function (fulfilled) {// call this function when the promise state changes to fulfilled}, function (rejected) {// call this function when the promise state changes to rejected }, function (progress) {// call this function when the progress information is returned });

If promise supports the following additional methods, it is called an interactive promise.

  • Get (propertyName)

Obtain an attribute on the final value of the current promise. The returned value is a new promise.

  • Call (functionName, arg1, arg2 ,...)

Call a method on the final value of promise. The return value is also a new promise.

Promises/B specification
Based on Promises/A, Promises/B defines A set of APIs to be implemented by the promise module.

When (value, callback, errback_opt)
If the value is not a promise, the next event cycle callback will be called, and the value will be used as the incoming value of callback. If the value is a promise and the status of promise has been completed or changed to completed, the callback of the next event loop will be called, and the resolve value will be passed into callback; if the promise status has failed or becomes failed, the next event cycle errback will be called, and the reason will pass in errback as the reason for failure.

Asap (value, callback, errback_opt)
The biggest difference from when is that if value is not a promise, it will be executed immediately and will not wait until the next event loop.

Enqueue (task Function)
Call the task method cyclically as quickly as possible in the next event.

Get (object, name)
Returns a promise that obtains the object attributes.

Post (object, name, args)
Returns the promise that calls the object method.

Put (object, name, value)
Returns a promise for modifying object attributes.

Del (object, name)
Returns a promise for deleting object attributes.

MakePromise (descriptor Object, fallback Function)
Returns a promise object, which must be a callable function or an instantiated constructor.

  • The first parameter accepts a description object. The object structure is as follows,

{ "when": function(errback){...}, "get": function(name){...}, "put": function(name, value){...}, "post": function(name, args){...}, "del": function(name){...}, } 

Each handle registered above returns a resolved value or promise.

  • The second parameter accepts a fallback (message,... args) function. When no promise object finds the corresponding handle, this function is triggered and a resolved value or promise is returned.

Defer ()
Returns an object that contains a resolve (value) method and a promise attribute.
When the resolve (value) method is called for the first time, the status of the promise attribute changes to complete, and the status of all promise that observe the promise before or after is changed to complete. If the value parameter is not a promise, it is encapsulated into a promise ref. The resolve method ignores all subsequent calls.

Reject (reason String)
Returns a promise marked as failed.
When the when (message) method is called on a failed promise, one of the following two methods is used:
1. If errback exists, errback will be called using reason as the parameter. The when method returns the returned value of errback.
2. If errback does not exist, the when method returns a promise object in the new reject State, with the same reason as the parameter.

Ref (value)
If value is a promise object, the value itself is returned. Otherwise, a resolved promise is returned, carrying the following handle.
1. when (errback), ignore errback and return the resolved Value
2. get (name) returns the corresponding attribute of the resolved value.
3. put (name, value), set the corresponding attribute of the resolved value.
4. del (name): Delete the corresponding attribute of the resolved value.
5. post (name, args), call the corresponding method of the resolved value.
6. A reject is returned for all other calls and the reason for carrying "Promise does not handle NAME" is returned.

IsPromise (value) Boolean
Determines whether an object is promise.

Method (name String)
Obtain a promise that returns the method corresponding to the name. The return value is the method corresponding to "get", "put", "del", and "post", but will be returned cyclically in the next event.

Promises/D Specification
To enhance the interoperability between different promise implementations, the Promises/D specification makes further agreements on promise objects and Promises/B specifications. To achieve the Duck type effect (Duck-type Promise ).

To put it simply, the Promises/D specification has done two things,

1. How to determine whether an object is of the Promise type.
2. add details to the Promises/B specification.
Identifies a Promise object
The Promise object must be the promiseSend method.
1. In the context of the promise library, if the object contains the promiseSend method, it can be identified as a promise object.
2. The promiseSend method must accept an operation name as the first parameter.
3. The operation name is an extensible set. Below are some reserved names
1. when, the third parameter must be the rejection callback.
1. The rejection callback must accept a rejection reason (which can be any value) as the first parameter.
2. get. The third parameter is the attribute name (string type)
3. put. The third parameter is the attribute name (string type), and the fourth parameter is the new attribute value.
4. del. The third parameter is the attribute name.
5. post. At this time, the third parameter is the property name of the method, and the next parameter is the call parameter of the method.
6. isDef
4. The second parameter of the promiseSend method is the resolver method.
5. The promiseSend method may accept variable parameters.
6. The promiseSend method must return undefined.

Supplement to Promises/B specifications
In the Promises/D specification, the ref, reject, def, and defer methods defined in Promises/B are further detailed. These details are omitted here.

Promises/A + Specification
The Promises/A/B/D specifications mentioned above are all proposed by the CommonJS organization. Promises/A + is published by A self-called Promises/A + organization, this specification is supplemented and revised on the basis of Promises/A to improve the interoperability between promise implementations.

Promises/A + supplements the. then method in detail, defines the detailed Promise Resolution Procedure process, and uses the. then method as the object identification method of promise.

In addition, Promises/A + provides compatibility testing tools to determine the compatibility of each implementation.

Implement a mini version of Promise
With so many rules mentioned above, we can now look at how to implement a simple and short Promise.

1. State Machine

var PENDING = 0;var FULFILLED = 1;var REJECTED = 2;function Promise() { // store state which can be PENDING, FULFILLED or REJECTED var state = PENDING; // store value or error once FULFILLED or REJECTED var value = null; // store sucess & failure handlers attached by calling .then or .done var handlers = [];}

2. status changes
Only two status changes are supported: fulfill and reject.

// ...function Promise() {  // ... function fulfill(result) {  state = FULFILLED;  value = result; } function reject(error) {  state = REJECTED;  value = error; }}

The fulfill and reject methods are relatively low-level. Generally, more advanced resolve methods are open to the outside.

// ...function Promise() { // ... function resolve(result) {  try {   var then = getThen(result);   if (then) {    doResolve(then.bind(result), resolve, reject)    return   }   fulfill(result);  } catch (e) {   reject(e);  } }}

The resolve method can take one common value or another promise as the parameter. If one promise is accepted as the parameter, wait for it to complete. Promise cannot be fulfill by another promise, so the resolve method must be enabled. The resolve method depends on the following help methods:

/** * Check if a value is a Promise and, if it is, * return the `then` method of that promise. * * @param {Promise|Any} value * @return {Function|Null} */function getThen(value) { var t = typeof value; if (value && (t === 'object' || t === 'function')) {  var then = value.then;  if (typeof then === 'function') {   return then;  } } return null;}/** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. * * @param {Function} fn A resolver function that may not be trusted * @param {Function} onFulfilled * @param {Function} onRejected */function doResolve(fn, onFulfilled, onRejected) { var done = false; try {  fn(function (value) {   if (done) return   done = true   onFulfilled(value)  }, function (reason) {   if (done) return   done = true   onRejected(reason)  }) } catch (ex) {  if (done) return  done = true  onRejected(ex) }}

Here the recursion between resolve and doResolve is clever and used to process layer-by-layer nesting of promise (the value of promise is a promise ).

Constructor

// ...function Promise(fn) {  // ...  doResolve(fn, resolve, reject);}

. Done method

// ...function Promise(fn) { // ... function handle(handler) {  if (state === PENDING) {   handlers.push(handler);  } else {   if (state === FULFILLED &&    typeof handler.onFulfilled === 'function') {    handler.onFulfilled(value);   }   if (state === REJECTED &&    typeof handler.onRejected === 'function') {    handler.onRejected(value);   }  } } this.done = function (onFulfilled, onRejected) {  // ensure we are always asynchronous  setTimeout(function () {   handle({    onFulfilled: onFulfilled,    onRejected: onRejected   });  }, 0); } // ...}

. Then Method

// ...function Promise(fn) {  // ...  this.then = function (onFulfilled, onRejected) {   var self = this;   return new Promise(function (resolve, reject) {    return self.done(function (result) {     if (typeof onFulfilled === 'function') {      try {       return resolve(onFulfilled(result));      } catch (ex) {       return reject(ex);      }     } else {      return resolve(result);     }    }, function (error) {     if (typeof onRejected === 'function') {      try {       return resolve(onRejected(error));      } catch (ex) {       return reject(ex);      }     } else {      return reject(error);     }    });   });  }  // ...}

$. Promise
In versions earlier than jQuery 1.8, the then method of jQuery is only a speed-writing method that can call the callback done, fail, and progress at the same time, the then of Promises/A standards is more like the pipe of jQuery in terms of behavior. JQuery 1.8 fixed this issue and made then a synonym for pipe. However, due to backward compatibility issues, jQuery's Promise won't be very attractive to anyone about Promises/.

In the Promises/A specification, whether the Promise object generated by the then method is executed or rejected depends on whether the callback called by the then method returns A value or throws an error. It is a bad idea to throw an error in the callback of the JQuery Promise object because the error will not be captured.

Summary
The last example reveals that the key to Promise implementation is to implement the doResolve method and trigger the callback after completion. To ensure asynchronous setTimeout (fun, 0), it is a key step.

Promise has always been quite handy, and it optimizes the code structure during node. js asynchronous processing. However, I am a little confused and curious about how it works, so I spent some time reviewing and translating the Promise specifications to fully understand the details of Promise.

The above is an introduction to the use of Promise in JavaScript, and I hope it will be helpful for everyone.

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.