RxJS Observables 的 Promise.all 行为?

Posted

技术标签:

【中文标题】RxJS Observables 的 Promise.all 行为?【英文标题】:Promise.all behavior with RxJS Observables? 【发布时间】:2016-06-07 02:08:55 【问题描述】:

在 Angular 1.x 中,我有时需要发出多个 http 请求并对所有响应进行处理。我会将所有的承诺放在一个数组中并调用Promise.all(promises).then(function (results) ...)

Angular 2 最佳实践似乎指向使用 RxJS 的 Observable 来替代 http 请求中的承诺。如果我有两个或多个从 http 请求创建的不同 Observable,是否有等效于 Promise.all()

【问题讨论】:

【参考方案1】:

模拟Promise.all 的更直接的替代方法是使用forkJoin 运算符(它并行启动所有可观察对象并加入它们的最后一个元素):

documentation 相关链接:Cf. RxJS: concat three promises, distinguish results

有点超出范围,但如果有帮助,关于链接承诺的主题,您可以使用简单的flatMap:Cf. RxJS Promise Composition (passing data)

【讨论】:

如果我有 2 个调用,一个返回承诺,另一个返回 observable,我可以使用 forkjoin 吗?或 promise.all() ?或者没有,我必须让这 2 个函数返回相同类型的 promises 或 observable? 请帮忙,当作为参数传递的可观察对象不发出值时,forkJoin 不起作用。我有 void Observables,但仍想使用 forkJoin 功能,但它不起作用【参考方案2】:

使用 RxJs v6 更新 2019 年 5 月

发现其他答案很有用,并希望为 Arnaud 提供的关于 zip 用法的答案提供一个示例。

这是一个 sn-p,显示了 Promise.all 和 rxjs zip 之间的等价性(另请注意,在 rxjs6 中,现在如何使用“rxjs”而不是作为运算符导入 zip)。

import  zip  from "rxjs";

const the_weather = new Promise(resolve => 
  setTimeout(() => 
    resolve( temp: 29, conditions: "Sunny with Clouds" );
  , 2000);
);

const the_tweets = new Promise(resolve => 
  setTimeout(() => 
    resolve(["I like cake", "BBQ is good too!"]);
  , 500);
);

// Using RxJs
let source$ = zip(the_weather, the_tweets);
source$.subscribe(([weatherInfo, tweetInfo]) =>
  console.log(weatherInfo, tweetInfo)
);

// Using ES6 Promises
Promise.all([the_weather, the_tweets]).then(responses => 
  const [weatherInfo, tweetInfo] = responses;
  console.log(weatherInfo, tweetInfo);
);

两者的输出相同。运行上面给出:

 temp: 29, conditions: 'Sunny with Clouds'  [ 'I like cake', 'BBQ is good too!' ]
 temp: 29, conditions: 'Sunny with Clouds'  [ 'I like cake', 'BBQ is good too!' ]

【讨论】:

【参考方案3】:

forkJoin 也可以正常工作,但我更喜欢combineLatest,因为您不必担心它会占用 observables 的最后一个值。这样,只要它们中的任何一个也发出新值(例如,您按时间间隔或其他方式获取),您就可以得到更新。

【讨论】:

这不符合我目前的需求,但我肯定会很快使用它。 这并没有实现与 Promise.all() 相同的行为,但它类似于 Promise.any() 如果我有 2 个调用,一个返回承诺,另一个返回 observable,我可以使用 forkjoin 吗?或 promise.all() ?或者没有,我必须让这 2 个函数返回相同类型的 promises 或 observable? @JoeSleiman 有点晚了,但你可以选择你的立场:Observable.fromPromise() 和 Observable.zip(),或 Obserable.toPromise() 和 Promise.all()【参考方案4】:

在reactivex.io forkJoin 实际上指向Zip,它为我完成了这项工作:

let subscription = Observable.zip(obs1, obs2, ...).subscribe(...);

【讨论】:

"这意味着 forkJoin 不会发出多次,并且会在之后完成。如果您不仅需要在传递的 observables 的生命周期结束时发出组合值,而且还需要在整个生命周期结束时发出组合值,请尝试combineLatest 或 zip 代替。” rxjs-dev.firebaseapp.com/api/index/function/forkJoin forkJoin 等待所有 observables 结束,而 zip 在所有输入发出它们的第一个值时发出一个数组。 zip 可能会发出很多次。如果你有 http-calls,那没什么区别。 好吧,我现在明白了,干杯。我没有意识到语言部分会扩展 -_-

以上是关于RxJS Observables 的 Promise.all 行为?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6 / Rxjs - 如何基础:observables 成功,错误,最后

在 Angular2 中使用 RxJS 链接 observables

取消订阅 Rxjs Observables

Angular RXJS Observables或Subjects在内部传递数字

Rxjs:使用 scan 或 mergeMap 或任何 rxjs 在 X 秒后将 observables 数据流(grpc 服务)组合成一个数组

RxJS Observables 的 Promise.all 行为?