Книга: Angular 2 Cookbook
Назад: Understanding and implementing basic Promises
Дальше: Creating Promise wrappers with Promise.resolve() and Promise.reject()

Chaining Promises and Promise handlers

Much of the purpose of promises is to allow the developer to serialize and reason about independent asynchronous actions. This can be accomplished by utilizing the Promise chaining feature.

Note

The code, links, and a live example of this are available at .

How to do it...

The promise handler definition method then() returns another promise, which can have further handlers defined upon it—in a handler called chain:

var successHandler = () => { console.log('called'); };      var p = new Promise((resolve, reject) => { resolve(); })     .then(successHandler)     .then(successHandler)     .then(successHandler);      // called   // called   // called   

Chained handlers' data handoff

Chained handlers can pass data to their subsequent handlers in the following manner:

var successHandler = (val) => {      console.log(val);      return val+1;   };      var p = new Promise((resolve, reject) => { resolve(0); })     .then(successHandler)     .then(successHandler)     .then(successHandler);      // 0   // 1   // 2   

Rejecting a chained handler

Returning normally from a promise handler (not the executor) will, by default, signal child promise states to become resolved. However, if either the executor or the subsequent handlers throw an uncaught exception, they will, by default, reject; this will serve to catch the exception:

const p = new Promise((resolve, reject) => {      // executor will immediately throw an exception, forcing     // a reject     throw 123;    })   .then(     // child promise resolved handler     data => console.log('resolved', data),      // child promise rejected handler     data => console.log('rejected', data));      // "rejected", 123   

Note

Note that the exception, here a number primitive, is the data that is passed to the rejection handler.

How it works...

A Promise reaching a final state will trigger child promises to follow it in turn. This simple but powerful concept allows you to build broad and fault-tolerant promise structures that elegantly mesh collections of dependent asynchronous actions.

There's more...

The topology of promises lends itself to some interesting utilization patterns.

Promise handler trees

Promise handlers will execute in the order that the promises are defined. If a promise has multiple handlers attached to a single state, then that state will execute all its handlers before resolving the following chained promise:

const incr = val => {     console.log(val);     return ++val;   };      var outerResolve;   const firstPromise = new Promise((resolve, reject) => {      outerResolve = resolve;    });      // define firstPromise's handler   firstPromise.then(incr);   // append another handler for firstPromise, and collect   // the returned promise in secondPromise   const secondPromise = firstPromise.then(incr);   // append another handler for the second promise, and collect   // the returned promise in thirdPromise   const thirdPromise = secondPromise.then(incr);      // at this point, invoking outerResolve() will:   // resolve firstPromise; firstPromise's handlers executes   // resolve secondPromise; secondPromises's handler executes   // resolve thirdPromise; no handlers defined yet      // additional promise handler definition order is   // unimportant; they will be resolved as the promises   // sequentially have their states defined   secondPromise.then(incr);   firstPromise.then(incr);   thirdPromise.then(incr);      // the setup currently defined is as follows:   // firstPromise -> secondPromise -> thirdPromise   // incr()          incr()           incr()   // incr()          incr()   // incr()      outerResolve(0);   // 0   // 0   // 0   // 1   // 1   // 2   

Note

Since the return value of a handler decides whether or not the promise state is resolved or rejected, any of the handlers associated with a promise is able to set the state—which, as you may recall, can only be set once. The defining of the parent promise state will trigger the child promise handlers to be executed.

It should now be apparent how the trees of the promise functionality can be derived from the combination of promise chaining and handler chaining. When used properly, they can yield extremely elegant solutions for difficult and ugly asynchronous action serializations.

catch()

The catch() method is a shorthand for promise.then(null, errorCallback). Using it can lead to slightly cleaner promise definitions, but it is nothing more than syntactical sugar:

var outerReject;   const p = new Promise((resolve, reject) => {     outerReject = reject;   })   .catch(() => console.log('rejected!'));      outerReject();   // "rejected"   

Tip

It is also possible to chain p.then().catch(). An error thrown by the original promise will propagate through the promise created by then(), cause it to reject, and reach the promise created by catch(). It creates one extra level of promise indirection, but to an outside observer, it will behave the same.

See also

  • Understanding and implementing basic Promises gives an extensive rundown of how and why to use Promises
  • Creating Promise wrappers with Promise.resolve() and Promise.reject() demonstrates how to use the core Promise utilities
Назад: Understanding and implementing basic Promises
Дальше: Creating Promise wrappers with Promise.resolve() and Promise.reject()

thank you
Flame
cant read the code since it is all on a single line. Also this comments section is russian
Rakuneque
DATA COLLECTION AND ANALYSIS Two reviewers extracted data and assessed methodological quality independently lasix torsemide conversion Many others were in that space already