等待多个承诺完成

Posted

技术标签:

【中文标题】等待多个承诺完成【英文标题】:Wait for multiple promises to finish 【发布时间】:2016-10-16 22:33:05 【问题描述】:

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

如何等待所有这些,然后执行回调函数?

代码:

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

Observable.forkJoin 为我工作。 Rx.Observable.forkJoin 没有。【参考方案2】:

使用Promise.all():

Promise.all(iterable) 方法返回一个当 iterable 参数中的所有 Promise 都已解析时解析的 Promise,或者以第一个被拒绝的 Promise 的原因拒绝。

语法

Promise.all(iterable);

参数

可迭代

一个可迭代的对象,例如一个数组。请参阅可迭代。

【讨论】:

【参考方案3】:

你可以使用

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

另见https://developer.mozilla.org/en/docs/Web/javascript/Reference/Global_Objects/Promise/all

【讨论】:

我要补充一点,如果这些承诺中的任何一个被拒绝,Promise.all 将立即拒绝(无论其他承诺是否完成)并且then 将被跳过。如果您需要运行doSomething(),无论它们成功还是失败,您都需要分别运行catch,然后分别返回Promise.resolve() 对于Promise.all(),他们会一个接一个地执行,还是同时执行? 所有调用都会立即执行,然后Promise.all() 只是等待所有这些承诺在它自己完成之前完成。这不是Promise.all 功能。使用此代码Promise.all([ this.storage.remove(key1),, ...]);` this.storage.remove(key1) 被调用,并且只有返回值(Promise)被添加到传递给Promise.all(...)的数组中【参考方案4】:

我不熟悉 IONIC,但假设 storage.remove 正在返回一个承诺,我建议您使用 observables 中的 forkJoin 运算符。

forkJoin 接受一个 observable 数组并等待所有项目的执行。

请注意,我必须从 .remove 方法返回的每个承诺中创建 3 个新的可观察对象。

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

【讨论】:

【参考方案5】:

对 Promises 使用 Promise.all,对 Observables 使用 Observable.forkJoin

因为问题是关于 angular(2+) 的,你可能应该使用 Observable 而不是 Promise。我将添加一个对我有用的 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() 来处理响应

【讨论】:

【参考方案6】:

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

【讨论】:

以上是关于等待多个承诺完成的主要内容,如果未能解决你的问题,请参考以下文章

等待内部带有承诺的 forEach 完成

jQuery Deferred - 等待多个 AJAX 请求完成 [重复]

等待循环中调用的所有承诺完成

如何承诺等待所有对象完成然后推送到数组?

承诺等待得到解决而不返回

Mocha 在运行测试之前似乎没有等待承诺链完成