簡體   English   中英

Angular / RxJS:帶有可觀察項的嵌套服務調用

[英]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完成上述操作的一種方法。

  1. 使用from將promise轉換為可觀察的。
  2. 在外部管道中,調用switchMap以便您可以調用另一個可觀察對象,並將其作為外部可觀察對象的結果返回。 您正在切換執行上下文。
  3. 在switchMap內,像以前一樣執行子項的映射,然后使用forkJoin創建所有元素的諾言的Observable。 一旦所有承諾都完成,ForkJoin將發出所有結果的數組。 就像promise.all
  4. 像以前一樣計划添加項目,然后返回原始項目。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM