簡體   English   中英

RxJS 可觀察的 forkJoin 未並行執行

[英]RxJS Observable forkJoin Not Executing in Parallel

我有以下代碼,對於我的一生,無法弄清楚為什么請求不會同時執行。 我對 RxJS 和 observables 還是陌生的,因此對於改進以下代碼的任何幫助也將不勝感激。 基本上,我在后端調用 REST API 以獲取一些數據。 然后,對於該數據數組中的每個元素,我正在向不同的端點發出另一個請求(因此使用“forkJoin”運算符)。 所有請求都一次發送,但它們似乎仍然一個接一個地執行,而不是同時執行。

this.sites$.subscribe(data => {

    // data.forEach(element => {
    //     this.siteCaptureMap[element.id] = new CaptureData();
            
    //     this.sitesService.getCaptureData(element.nameOrNumber, element.owner.name).subscribe(data => {
    //         this.siteCaptureMap[element.id].count = data.length;
    //     });
    // });

    var obs: Observable<any>[] = [];
    for (var _i = 0; _i < data.length; _i++) {
        this.siteCaptureMap[data[_i].id] = new CaptureData();
        this.siteCaptureMap[data[_i].id].id = _i;
        obs.push(this.sitesService.getCaptureData(data[_i].nameOrNumber, data[_i].owner.name));
    }

    forkJoin(obs).subscribe(results => {
        for (var _i = 0; _i < results.length; _i++) {
            this.siteCaptureMap[data[_i].id].count = results[_i].length;
        }
    });


    this.dataSource.data = data;
    this.dataSource.filteredData = data;
});

再次,任何幫助將不勝感激。 如果我需要澄清任何事情或提供任何其他代碼片段,請告訴我! 謝謝!

嵌套的subscribe可能會導致 memory 泄漏,並且很難取消訂閱,因此每當您嵌套了subscribe時,請考慮switchMapconcatMapmergeMap

它們都有微小的變化,但它們從以前的 observable 切換到新的 observable。 這篇 文章解釋了這些差異。

對你來說,我會嘗試做:

import { switchMap } from 'rxjs/operators';

...
this.sites$.pipe(
  switchMap(data => {
    let obs: Observable<any>[] = [];
    for (let _i = 0; _i < data.length; _i++) {
        this.siteCaptureMap[data[_i].id] = new CaptureData();
        this.siteCaptureMap[data[_i].id].id = _i;
        obs.push(this.sitesService.getCaptureData(data[_i].nameOrNumber, data[_i].owner.name));
    }

    return forkJoin(obs);
  }),
).subscribe(results => {
        for (let_i = 0; _i < results.length; _i++) {
            this.siteCaptureMap[data[_i].id].count = results[_i].length;
        }

        this.dataSource.data = data;
        this.dataSource.filteredData = data;
    });

附帶說明是使用letconst而不是var

此外,如果您看到所有請求同時發出,這就是您所希望的。 如果它連續返回,則可能是瀏覽器或服務器造成的。

首先,我將重新排列代碼以使其更符合 rxjs 的習慣,刪除嵌套訂閱並使用pipe並使其更具功能風格。 內聯注釋試圖解釋變化

this.sites$.pipe(
  // this is the rxjs map operator that transform the data received from
  // the rest api into something different
  map(data => {
    // I create the obs array using the map method of JS arrays - this is 
    // NOT the rxjs map operator
    obs = data.map((element, _i) => {
       this.siteCaptureMap[element.id] = new CaptureData();
       this.siteCaptureMap[element.id].id = _i;
       return this.sitesService.getCaptureData(element.nameOrNumber, element.owner.name)
    });
    // return both the array of observables and the data
    return [data, obs];
  }),
  // concatMap makes sure that you wait for the completion of the rest api
  // call and the emission of the data fetched before you execute another
  // async operation via forkJoin
  concatMap(([data, obs]) => forkJoin(obs).pipe(
    // this is the rxjs map operator used to return not only the results
    // received as result of forkJoin, but also the data received with the
    // first rest call - I use this operator to avoid having to define 
    // a variable where to store 'data' and keep the logic stateless 
    map(results => ([data, results]))
  ))
).subscribe(([data, results]) => {
  // here I use forEach to loop through the results and perform
  // your logic
  results.forEach((res, _i) => this.siteCaptureMap[data[_i].id].count = res.length)
})

我覺得這個表格更符合rxjs及其功能精神,應該和你原來的表格是等價的。

同時,我很想知道您為什么說您的代碼當時在forkJoin one 中執行調用。

順便說一句,如果您有興趣查看 rxjs 和 http 的常見使用模式,您可以閱讀這篇文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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