Bas van Dijk
Bas van Dijk

Reputation: 10713

Wait for multiple promises to finish

I am using the SQLStorage from the Ionic platform. The remove function returns a promise. In my code I need to remove multiple values. When these are all finished I need to execute some code.

How can I wait for all of these and then execute a callback function?

Code:

removeAll() {    
  this.storage.remove(key1);
  this.storage.remove(key2);
  this.storage.remove(key3);    
}

Nesting all is a bad practise so I am looking for a decent solution :)

removeAll() {
  return this.storage.remove(key1).then(() => {
    this.storage.remove(key2).then(() => {
      this.storage.remove(key3);        
    });
  });
};

Upvotes: 69

Views: 82343

Answers (6)

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657406

You can use

removeAll() {
  Promise.all([
    this.storage.remove(key1),
    this.storage.remove(key2),
    this.storage.remove(key3),
  ]).then(value => doSomething());

value is an array that contains the return values of each async call passed to Promise.all([...]) matching in order.

See also https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Upvotes: 104

Sandro Almeida
Sandro Almeida

Reputation: 51

use Promise.all for Promisses and Observable.forkJoin for Observables

as the question is about angular(2+) and you problably should have been using Observable instead of promises. i`ll add a GET example that worked for me:

import {Observable} from 'rxjs/Rx';
    
Observable.forkJoin(
      this._dataService.getOne().map(one => this.one = one),
      this._dataService.getTwo().map(two => this.two = two),
      this._dataService.getN().map(n => this.n = n),
     )
    ).subscribe(res => this.doSomethingElse(this.one, this.two, this.n)); 

note the use one .map() to handle the response rather than .subscribe()

Upvotes: 3

Pankaj Parkar
Pankaj Parkar

Reputation: 136154

You could use Observable.forkJoin from rxjs by providing an array of all the observables/promises. This needs to be done before performing the operation. It's similar to Angular 1's $q.all.

rxjs version <= 6

Observable.forkJoin([
   this.storage.remove(key1), 
   this.storage.remove(key2),
   this.storage.remove(key3)
])
.subscribe(t=> {
    var firstResult = t[0];
    var secondResult = t[1];
});

rxjs version > 6

import {forkJoin} from 'rxjs';

forkJoin([
   this.storage.remove(key1), 
   this.storage.remove(key2),
   this.storage.remove(key3)
])
.subscribe(t=> {
    var firstResult = t[0];
    var secondResult = t[1];
});

Upvotes: 38

Daniel Pliscki
Daniel Pliscki

Reputation: 1923

I'm not familiar with IONIC, but assuming that storage.remove is returning a promise I would suggest you to use forkJoin operator from observables.

forkJoin takes an array of observables and awaits the execution of all items.

Just notice that I had to create 3 new observables from each promise returned by the .remove method.

Observable.forkJoin([
   Observable.fromPromise(this.storage.remove(key1)), 
   Observable.fromPromise(this.storage.remove(key2)),
   Observable.fromPromise(this.storage.remove(key3))
])
.subscribe(data => {
    console.log(data[0]);
    console.log(data[1]);
    console.log(data[2]);
});

Upvotes: 4

user4229770
user4229770

Reputation:

On rxjs version > 6 You can do something like this:

import {forkJoin} from 'rxjs';

and do instead of Observable.forkJoin this:

forkJoin([
  this.service1.get(),
  this.service2.get()
]).subscribe(data => {
  this.data1= data[0];
  this.data2 = data[1];

Upvotes: 5

JB Nizet
JB Nizet

Reputation: 691755

Use Promise.all():

The Promise.all(iterable) method returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.

Syntax

Promise.all(iterable);

Parameters

iterable

An iterable object, such as an Array. See iterable.

Upvotes: 3

Related Questions