Книга: Angular 2 Cookbook
Назад: Implementing Promise barriers with Promise.all()
Дальше: Converting a Promise into an Observable

Canceling asynchronous actions with Promise.race()

ES6 introduces Promise.race(), which is absent from the $q spec in Angular 1. Like Promise.all(), this static method accepts an iterable collection of promise objects; whichever one resolves or rejects first will become the result of the promise wrapping the collection. This may seem like unusual behavior, but it becomes quite useful when you're building a cancellation behavior into the system.

Note

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

Getting ready

Suppose you started with a simple promise that resolves to a value after 3 seconds:

const delayedPromise = new Promise((resolve, reject) =>      setTimeout(resolve.bind(null, 'foobar'), 3000))   .then(val => console.log(val));   

You would like to have the ability to detach a part of your application from waiting for this promise.

How to do it...

A simple solution would be to expose the promise's reject handler and just invoke it from whatever is to perform the cancelation. However, it is preferable to stop waiting for this promise instead of destroying it.

Note

A concrete example of this would be a slow but critical HTTP request that your application makes. You might not want the UI to wait for it to complete, but you may have resolve handlers attached to the request that you still want to handle the result, once it is returned.

Instead, you can take advantage of Promise.race() and introduce a cancellation promise alongside the original one:

// Use this method to capture the cancellation function   var cancel;       const cancelPromise = new Promise((resolve, reject) => {      cancel = reject;    });    const delayedPromise = new Promise((resolve, reject) =>      setTimeout(resolve.bind(null, 'foobar'), 3000));       // Promise.race() creates a new promise   Promise.race([cancelPromise, delayedPromise])   .then(     val => console.log(val),      () => console.error('cancelled!'));      // If you invoke cancel() before 3 seconds elapses   // (error) "cancelled!"         // Instead, if 3 seconds elapses   // "foobar"   

Now, if delayedPromise resolves first, the promise created by Promise.race() will log the value passed to it here, foobar. If, however, you invoke cancel() before it happens, then that same Promise will print a cancelled! error.

How it works...

Promise.race() just waits for any of its inner promises to arrive at the final state. It creates and returns a new promise that is beholden to the state of the contained promises. When it observes that any of them transitions to the final state, the new promise also assumes this state.

Note

In this example, the executor of cancelPromise and delayedPromise are invoked before Promise.race() is called. Since promises only care about the state of other promises, it isn't important that the promises passed to Promise.race() need to be already technically started.

Note that the use of Promise.race() doesn't affect the implementation of delayedPromise. Even when cancel() is invoked, delayedPromise will still be resolved and its handlers will still be executed normally, unaware that the surrounding Promise.race() has already been rejected. You can prove this to yourself by adding a resolve handler to delayedPromise, invoking cancel() and seeing the resolve handler of delayedPromise being executed anyway:

var cancel;    const cancelPromise = new Promise((resolve, reject) => {      cancel = reject;    });    const delayedPromise = new Promise((resolve, reject) =>       setTimeout(resolve.bind(null, 'foobar'), 3000))   .then(() => console.log('still resolved!'));       Promise.race([ cancelPromise, delayedPromise ])   .then(     val => console.log(val),      () => console.error('cancelled!'));      cancel();   // (error) cancelled!      // After 3 seconds elapses   // "still resolved!"   

See also

  • Creating Promise wrappers with Promise.resolve() and Promise.reject() demonstrates how to use the core Promise utilities
  • Implementing Promise barriers with Promise.all() show you how Promises can be composable
Назад: Implementing Promise barriers with Promise.all()
Дальше: Converting a Promise into an Observable

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