Javascript 如何';等等';对于RxJS中的两个观测值

Javascript 如何';等等';对于RxJS中的两个观测值,javascript,angular,rxjs,reactive-programming,Javascript,Angular,Rxjs,Reactive Programming,在我的应用程序中,我有如下内容: this._personService.getName(id) .concat(this._documentService.getDocument()) .subscribe((response) => { console.log(response) this.showForm() }); //Output: // [getnameResu

在我的应用程序中,我有如下内容:

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

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

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

然后我得到两个独立的结果,首先是
\u personService
,然后是
\u documentService
。如何在调用this.showForm()完成一个操作之前等待这两个结果。

您可以像下面这样使用“zip”或“buffer”

function getName() {
    return Observable.of('some name').delay(100);
}

function getDocument() {
    return Observable.of('some document').delay(200);
}

// CASE1 : concurrent requests
Observable.zip(getName(), getDocument(), (name, document) => {
    return `${name}-${document}`;
})
    .subscribe(value => console.log(`concurrent: ${value}`));

// CASE2 : sequential requests
getName().concat(getDocument())
    .bufferCount(2)
    .map(values => `${values[0]}-${values[1]}`)
    .subscribe(value => console.log(`sequential: ${value}`));

请看一看“combineLatest”方法,它可能适合这里。

上次更新:2020年5月。

组合相关测试(可观测) 从reactiveX:

每当任何可观测的输入发出一个值时,它就会使用所有输入的最新值计算一个公式,然后发出该公式的输出

(更新日期:2021年2月)

(可选语法):组合相关测试(可观察)


zip vs CombineTest (更新日期:2018年10月) 我之前建议使用
zip
方法。然而,对于某些用例,
combinelatetest
zip
有一些优势。因此,了解这些差异很重要

CombineTest
从可见光发射最新发射值。而
zip
方法按顺序发出发出的项目

例如,如果可观察的#1发出其3项,而可观察的#2发出其5项。使用
zip
方法的结果将是3rd两个
观测值的发射值

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


可观测的.zip(可观测的) (原始答案:2017年7月)Observable.zip方法解释如下:

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


旁注(适用于两种方法) 最后一个参数,我们提供了一个函数,
(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();
       })
使用
forkJoin()
观察方法

来自RXJS

当您有一组可观察对象并且只关心每个对象的最终发射值时,最好使用此运算符。这方面的一个常见用例是,如果您希望在页面加载(或某些其他事件)上发出多个请求,并且只希望在收到所有请求的响应时才采取操作。通过这种方式,它与您可能使用的方式类似

代码取自:

对我来说,这是最好的解决方案

const source = Observable.interval(500);
const example = source.sample(Observable.interval(2000));
const subscribe = example.subscribe(val => console.log('sample', val));
所以。。仅当第二个(示例)发射时-您将看到第一个(源)的最后一个发射值

在我的任务中,我等待表单验证和其他DOM事件。

这对我帮助很大。正如名称所述,它描述了以下组合运算符:

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

使用直接参数分解和自动添加类型的改进(当您使用typescript时)

const name$=this.\u personService.getName(id);
const document$=this.\u documentService.getDocument();
组合测试([name$,document$)。订阅([name,document])=>{
this.name=名称;
本文件=文件;
这是showForm();

});2021年6月

使用rxjs 6.6.7

像这样使用CombineTest,否则将被取消调整

combineLatest([a$ , b$]).pipe(
      map(([a, b]) => ({a, b})) //change to [a , b] if you want an array
    )
另请参见@nyxz post

zip-爱情鸟总是作为一个团队工作,只有当所有人 观察值返回新值

CombineTest-各付各的,在所有可观察到的情况下启动触发器 返回新值,然后等待无人,每次 任何一个可观察到的返回新值

withLatestFrom-主从机,master首先等待从机,然后 也就是说,只有当主控返回新的时,动作才会被触发 价值观

forkJoin-最终目的地,当所有可观察到时触发一次 已经完成


From:

forkJoin据我所知,由于
concat
@user3743222,您已经是了。在本例中,这些值是单独发出的。一个接一个。在forkJoin中,subscribe将得到一个结果-第一个和第二个响应的元组-这正是您所要求的?forkJoin并不总是有效的,因为它需要两个观察值才能“完成”。有时,您想同时启动“下一个”,但不一定是“完成”是否可以等待一个可观察对象的完成?我的可观察对象有另一个内部可观察对象,这反过来又依赖于http.get?在您2020年1月的更新中,为什么要将数组映射到对象?当您可以在subscribe方法中销毁数组时,这似乎是一个不必要的步骤。这将是我唯一的评论,其余的看起来不错。哦,我找了一个小时的CombineTest接线员。。。你有多少次取消联合观测的订阅?只需从CombinedLasts()返回的observable中取消订阅即可。subscribe()?@sharon182准确地说。是否可以用这个等待一个observable的完成?我的observable有另一个内部observable,它反过来依赖http.get?@HDJEMAI,如果你想在一个observable完成后做某事,您可以使用嵌套订阅吗?感谢您提供的第一个链接,即“RxJs Operators…”是必读的,也是您能得到的最好、最简单的解释
// 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();
       })
// 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();
       })
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];
});
const source = Observable.interval(500);
const example = source.sample(Observable.interval(2000));
const subscribe = example.subscribe(val => console.log('sample', val));
combineLatest([a$ , b$]).pipe(
      map(([a, b]) => ({a, b})) //change to [a , b] if you want an array
    )