[英]Angular/ RxJS: nested service calls with observables
我是RxJS可觀察對象的新手,正在嘗試解決一個相當簡單的用例。
在服務中,我首先進行http調用,以返回一個項目(作為可觀察的對象)。 該項目包含ID數組,其中一些重復。 對於每個不同的ID,我需要調用另一個http服務(再次返回一個observable),並將其返回值添加到原始項目中,以代替相應的ID。 這些調用應並行進行。 最后,每次通話結束后,我的服務應返回可觀察到的原始項目,現在已包含其子項目。
為了給出更好的主意,這是用promise而不是可觀察的東西看起來的樣子:
MyService() {
return HttpGetMainItem()
.then(item => {
var promises = _.uniq(item.subItems)
.map(sid => HttpGetSubItem(sid)
.then(subItem => {
// add to matching item.subItems
}));
// wait for all promises to complete and return main item
return Promise.all(promises).then(() => item);
});
}
用可觀察物完成此工作的最佳方法是什么?
編輯:從答案看來我不是很清楚。 帶有promises的示例只是為了清楚起見,在我的情況下,http調用實際上是Angular的HttpClient.get,因此它們返回的是observables-我正在尋找使用observables做的所有事情。
這是使用rxjs完成上述操作的一種方法。
from
將promise轉換為可觀察的。 switchMap
以便您可以調用另一個可觀察對象,並將其作為外部可觀察對象的結果返回。 您正在切換執行上下文。 forkJoin
創建所有元素的諾言的Observable。 一旦所有承諾都完成,ForkJoin將發出所有結果的數組。 就像promise.all
。 碼
from(HttpGetMainItem()).pipe(
switchMap(item =>
forkJoin(_.uniq(item.subItems).map(sid => HttpGetSubItem(sid)))
.pipe(
map(results => {
/* add results to matching items.subItems and */
return item;
})
)
)
);
我覺得這有點笨拙,因為需要保留根項目及其所需的嵌套。 您可以使用switchMap的選擇器參數來組合外部和內部可觀察對象。 您可以使用該參數來代替您在map()
使用的邏輯,並且由於兩個可觀察對象的結果都已傳遞,因此您不需要任何進一步的嵌套。
from(HttpGetMainItem()).pipe(
switchMap(
item => forkJoin(_.uniq(item.subItems).map(sid => HttpGetSubItem(sid))),
(item, results) => {
/* add results to matching items.subItems and */
return item;
}
)
);
我相信您需要這樣的東西:
import { from, forkJoin } from 'rxjs';
import { switchMap } from 'rxjs/operators';
itemWithSubItems$ = from(HttpGetMainItem()).pipe(
switchMap(item => {
const promises = _.uniq(item.subItems).map(item => HttpGetSubItem(item.sid));
return forkJoin(promises)
.map(resultArray => item.subItems = resultArray)
.map(_ => item);
})
);
首先獲取主要項目。 然后使用forkJoin解決所有子查詢並充實主要項目。 之后,只需返回主要項目即可。
也許您可以使用像async.each-> https://caolan.github.io/async/docs.html#each (可能是eachSeries)之類的庫。
就像這樣:
async.each(array, (obj, cb) => {
observable with obj in parameter and with subscriber result :
cb(err, subscriberRes);
}, (err, res) => {
console.log(res);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.