等待多个承诺完成

66

我正在使用Ionic平台的SQLStorage。 remove函数返回一个Promise。在我的代码中,我需要删除多个值。当这些都完成后,我需要执行一些代码。

如何等待它们全部完成,然后执行回调函数?

代码:

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

嵌套所有东西是一种不好的实践,因此我正在寻找一个合适的解决方案 :)

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

101

9
如果这些 Promise 中的任何一个被拒绝,Promise.all 将立即拒绝(无论其余的 Promise 是否已经完成),并且 then 将被跳过。如果您需要无论成功或失败都要运行 doSomething(),则需要单独使用 catch 来返回一个 Promise.resolve() - Manu Valdés
1
使用 Promise.all(),它们是一个接一个地执行还是同时执行? - Robouste
1
所有的调用都会立即执行, 然后 Promise.all() 只是等待所有这些 promise 完成之后再完成它自己。这不是一个 Promise.all 特性。使用这段代码 Promise.all([ this.storage.remove(key1),, ...]);会调用this.storage.remove(key1),只有返回值(一个 Promise)被添加到传递给 Promise.all(...)` 的数组中。 - Günter Zöchbauer

38
你可以使用rxjs中的Observable.forkJoin,通过提供所有observables/promises数组来执行操作。这需要在执行操作之前完成。这类似于Angular 1的$q.all

rxjs版本<=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];
});

1
Observable.forkJoin 对我有效。Rx.Observable.forkJoin 不行。 - My Stack Overfloweth

5
在`rxjs`版本大于6的情况下,您可以像这样进行操作:
import {forkJoin} from 'rxjs';

不要使用Observable.forkJoin,而是使用以下方法:

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

4
我不熟悉IONIC,但假设storage.remove返回一个Promise,我建议您使用observables的forkJoin操作符。

forkJoin接受observable数组并等待所有项执行。

请注意,我必须从每个.remove方法返回的Promise创建3个新的observables。

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]);
});


3

使用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.


3

对于 Promises,可以使用 Promise.all;对于 Observables,可以使用 Observable.forkJoin。

由于问题涉及 Angular(2+),您可能应该使用 Observable 而不是 promises。以下是一个 GET 示例,适用于我:

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)); 

注意使用.map()处理响应而不是.subscribe()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接