如何在 RxJS 中“等待”两个 observable

IT技术 javascript angular rxjs reactive-programming
2021-02-23 19:51:11

在我的应用程序中,我有类似的东西:

this._personService.getName(id)
      .concat(this._documentService.getDocument())
      .subscribe((response) => {
                  console.log(response)
                  this.showForm()
       });

 //Output: 
 // [getnameResult]
 // [getDocumentResult]

 // I want:
 // [getnameResult][getDocumentResult]

然后我得到两个分开的结果,第一个是_personService,然后是_documentService. 如何在调用之前等待两个结果this.showForm()完成然后操作每个结果。

6个回答

最后更新:2021 年 6 月。

RxJS v7: combineLatestWith

来自reactiveX文档

每当任何输入 Observable 发出一个值时,它都会使用来自所有输入的最新值计算一个公式,然后发出该公式的输出。

// Observables to combine
const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();
    
name$.pipe(
        combineLatestWith((name, document) => {name, document})
      )
      .subscribe(pair => {
           this.name = pair.name;
           this.document = pair.document;
           this.showForm();
       })

(已弃用)RxJS v6 combineLatest()

来自reactiveX文档

每当任何输入 Observable 发出一个值时,它都会使用来自所有输入的最新值计算一个公式,然后发出该公式的输出。

(更新:2021 年 2 月)

// Deprecated (RxJS v6)
// Observables to combine
const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();
    
name$.combineLatest(document$, (name, document) => {name, document})
    .subscribe(pair => {
           this.name = pair.name;
           this.document = pair.document;
           this.showForm();
       })

(替代语法): combineLatest(observables)

// Deprecated (RxJS v6)
// Observables to combine
const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();
    
combineLatest(name$, document$, (name, document) => ({name, document}))
    .subscribe(pair => {
           this.name = pair.name;
           this.document = pair.document;
           this.showForm();
       })

zip 与 combineLatest

(更新:2018 年 10 月) 我之前建议使用zip方法。但是,对于某些用例,combineLatestzip. 因此,了解差异很重要。

CombineLatest从 observables 发出最新发出的值。Whilezip方法顺序发出发出的项目

例如,如果 observable #1 发出它的第 3项,而 observable #2 发出它的第 5项。使用zip方法的结果将是两者的第三个发出的值observables

在这种情况下,使用的结果combineLatest将是5th3rd这感觉更自然。


Observable.zip(可观察的)

(原始答案:2017 年 7 月) reactiveX 文档中解释了 Observable.zip 方法

组合多个 Observable 以创建一个 Observable,其值是根据每个输入 Observable 的值按顺序计算的。

// Observables to combine
const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();
    
Observable
    .zip(name$, document$, (name: string, document: string) => ({name, document}))
    .subscribe(pair => {
           this.name = pair.name;
           this.document = pair.document;
           this.showForm();
       })

旁注(适用于两种方法)

我们提供了一个函数的最后一个参数(name: string, document: string) => ({name, document})是可选的。你可以跳过它,或者做更复杂的操作:

如果最新的参数是一个函数,则该函数用于根据输入值计算创建的值。否则,返回输入值的数组。

所以如果你跳过最后一部分,你会得到一个数组:

// Observables to combine
const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();
    
Observable
    .zip(name$, document$)
    .subscribe(pair => {
           this.name = pair['0'];
           this.document = pair['1'];
           this.showForm();
       })
是否可以等待一个 observable 的完成?,我的 observable 有另一个内部 observable,它又依赖于 http.get ?
2021-04-23 19:51:11
你如何取消订阅合并的 observables ?只是取消订阅由 combineLatest().subscribe() 返回的 observable 吗?
2021-04-24 19:51:11
OOOOHHHH,我一直在寻找 combineLatest 运算符一个小时......非常感谢
2021-05-01 19:51:11
combineLatest已被弃用,支持combineLatestWith,请参见此处:rxjs.dev/api/operators/combineLatest
2021-05-02 19:51:11
在 2020 年 1 月的更新中,为什么要将数组映射到对象?当您可以在 subscribe 方法中破坏数组时,这似乎是一个不必要的步骤。这将是我唯一的评论,其余的看起来不错。
2021-05-17 19:51:11

使用forkJoin()observables 的方法。检查此链接以供参考

来自 RXJS文档

当您有一组 observable 并且只关心每个的最终发出值时,最好使用此运算符。一个常见的用例是,如果您希望在页面加载(或某些其他事件)时发出多个请求,并且只想在收到所有响应时采取行动。通过这种方式,它类似于您使用Promise.all 的方式

forkJoin([character, characterHomeworld]).subscribe(results => {
  // results[0] is our character
  // results[1] is our character homeworld
  results[0].homeworld = results[1];
  this.loadedCharacter = results[0];
});

代码取自:https : //coryrylan.com/blog/angular-multiple-http-requests-with-rxjs

是否可以等待一个 observable 的完成?,我的 observable 有另一个内部 observable,它又依赖于 http.get ?
2021-04-28 19:51:11
@HDJEMAI 如果你想做某事。完成一个 observable 后,可以使用嵌套订阅吗?
2021-05-06 19:51:11
@YuweiHE 非常糟糕的建议,因为有 switchmap/flatmap 操作符。避免嵌套订阅
2021-05-10 19:51:11

The RxJS Operators for Dummies: forkJoin, zip, combineLatest, withLatestFrom帮了我很多。顾名思义,它描述了以下组合运算符:

它们中的任何一个都可能是您正在寻找的东西,具体取决于具体情况。查看文章了解更多信息。

感谢您提供的第一个链接,即“RxJs Operators ...”是必读的,也是您能得到的最好和最简单的解释
2021-05-21 19:51:11

使用直接参数分解并自动添加类型Hamid Asghari 答案的改进(当您使用typescript时)

const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();

combineLatest([name$, document$]).subscribe(([name, document]) => {
    this.name = name;
    this.document = document;
    this.showForm();
});

奖励:您还可以使用上述方法处理错误,如下所示

看看'combineLatest'方法,它可能适合这里。 http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-combineLatest

const { Observable } = Rx

const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();

Observable
    .combineLatest(name$, document$, (name, document) => ({ name, document }))
    .first() // or not, implementation detail
    .subscribe(({ name, document }) => {
        // here we have both name and document
        this.showForm()
    })