[英]How to 'wait' for two observables in RxJS
在我的應用程序中,我有類似的東西:
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()
之前如何等待兩個結果來完成然后操作每個結果。
從 reactiveX文檔:
每當任何輸入 Observable 發出一個值時,它都會使用來自所有輸入的最新值計算一個公式,然后發出該公式的輸出。
// Observables to combine
const name$ = this._personService.getName(id);
const document$ = this._documentService.getDocument();
name$.pipe(
combineLatestWith($document)
)
.subscribe(([name, document]) => {
this.name = name;
this.document = pair.document;
this.showForm();
})
從 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();
})
(更新:2018 年 10 月)我之前建議使用zip
方法。 但是,對於某些用例, combineLatest
比zip
有一些優勢。 因此,了解這些差異很重要。
CombineLatest
從 observables 發出最新的發射值。 而zip
方法按順序發出發出的項目。
例如,如果 observable #1 發出了它的第 3 個item,而 observable #2 發出了它的第 5 個item。 使用zip
方法的結果將是兩個observables
的第三個發射值。
在這種情況下,使用combineLatest
的結果將是5th和3rd 。 感覺更自然。
(原始答案:2017 年 7 月) Observable.zip 方法在reactiveX 文檔中進行了解釋:
組合多個 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();
})
使用 observables 的forkJoin()
方法。 檢查此鏈接以供參考
來自 RXJS文檔
當您有一組可觀察對象並且只關心每個對象的最終發出值時,最好使用此運算符。 一個常見的用例是,如果您希望在頁面加載(或其他事件)時發出多個請求,並且只想在收到所有人的響應時采取行動。 通過這種方式,它類似於您使用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
傻瓜的 RxJS 運算符:forkJoin、zip、combineLatest、withLatestFrom對我幫助很大。 顧名思義,它描述了以下組合運算符:
其中任何一個都可能是您正在尋找的東西,具體取決於具體情況。 查看文章了解更多信息。
改進了使用直接參數分解並自動添加類型的Hamid Asghari 答案(當您使用打字稿時)
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(); });
獎勵:您還可以使用上述方法處理錯誤,如下所示
import { combineLatest, of } from 'rxjs'; //... const name$ = this._personService.getName(id); const document$ = this._documentService.getDocument(); combineLatest([ name$.pipe( catchError( () => of(null as string ) ) ), document$.pipe( catchError( () => of(null as Document) ) ), // 'Document' is arbitrary type ]).subscribe(([name, document]) => { this.name = name; // or null if error this.document = document; // or null if error this.showForm(); });
2021 年 6 月
使用 rxjs 6.6.7
像這樣使用combineLatest否則被棄用
combineLatest([a$ , b$]).pipe(
map(([a, b]) => ({a, b})) //change to [a , b] if you want an array
)
另見@nyxz 帖子
zip - 愛情鳥,始終作為一個團隊工作,僅在所有可觀察對象返回新值時觸發
combineLatest - go dutch,一旦所有可觀察對象返回新值就開始觸發,然后等待無人,每次當任一可觀察對象返回新值時觸發。
withLatestFrom - 主從,主先等待從,之后,只有當主返回新值時才會觸發動作。
forkJoin - 最終目的地,當所有可觀察對象完成時觸發一次。
來自: https ://scotch.io/tutorials/rxjs-operators-for-dummies-forkjoin-zip-combinelatest-withlatestfrom/amp
看看 '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()
})
對我來說,這個 樣本是最好的解決方案。
const source = Observable.interval(500);
const example = source.sample(Observable.interval(2000));
const subscribe = example.subscribe(val => console.log('sample', val));
所以..只有當第二個(示例)發射時 - 你會看到第一個(源)的最后一個發射值。
在我的任務中,我等待表單驗證和其他 DOM 事件。
您可以使用“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}`));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.