簡體   English   中英

BehaviorSubject 和 concatMap 的副作用

[英]Side effects with BehaviorSubject and concatMap

這是我第一次嘗試 BehaviorSubject、異步管道和 concatMap,所以我在更新 DOM 中的數據時遇到了一些問題。

我有:

private profilesStore = new BehaviorSubject<any>(null);
profiles$ = this.profilesStore.asObservable();

  getUserProfiles(): Observable<Profile[]> {
    const headers = this.authService.getHeaders();
    return this.http.get<any>(`${API_URL}/profile`, { headers: headers })
      .pipe(
        catchError(err => throwError(err)),
        tap(res => this.profilesStore.next(res)),
        shareReplay()
      );
  }

接着

addProduct(profileId: any) {
    const headers = this.authService.getHeaders();
    return this.http.post<any>(`${apiUrl}/products/${profileId}`, {}, { headers: headers })
      .pipe(
        catchError(err => throwError(err)),
        concatMap(() => this.profileService.profiles$),
        map(profiles => {
          const selectedProfile = profiles.findIndex(profile => profile.id === profileId);
            profiles[selectedProfile].canEdit = true;
            return profiles;
        })
      );
  }

這個邏輯就像購物車邏輯。 我將產品添加到其中一個配置文件,以避免再次調用 api (getUserProfiles) 我修改配置文件 $ stream 並添加我想要的屬性(在本例中為 canEdit)但是當我從購物車中刪除產品時問題出現了並從 getUserProfiles() 恢復數據我知道,當我將 concatMap 與profiles$ 一起使用時,即使我沒有調用 function,我也會對 addProduct() 產生副作用,我的問題是......

為什么它繼續執行

map(profiles => {
          const selectedProfile = profiles.findIndex(profile => profile.id === profileId);
          profiles[selectedProfile].canEdit = true;
            return profiles;
        })

使用我過去作為參數傳遞的舊 profileId,即使我沒有調用 addProduct() function,如何避免這種情況?

將 observables 想象成一個水龍頭,一旦你訂閱它,水龍頭就永遠不會關閉。 只要有水,水就會一直流動。 只有當您取消訂閱它(或任何其他終止它的運營商)時,水龍頭才會關閉。

因此,在您執行addProfile()的那一刻,即使只是一次,它的 observable 將永遠打開,並且只要有數據(水)排放,即使您不調用 function,數據的排放仍將繼續addProfile()不再-> 而且,如果您調用 function 兩次,您實際上有兩個訂閱,即兩個水管和水龍頭; 這是大多數開發人員沒有注意的事情。

因此,當您第一次調用addProfile()時,並且由於您從未取消訂閱它,您實際上切換到收聽profiles$感謝

  concatMap(() => this.profileService.profiles$),

, 你的 stream 的數據實際上變成了監聽那個 BehaviourSubject 的變化,這就解釋了即使你不再調用addProfile()了,但是因為你更新了你的profiles$ ,排放量仍然是 go 通過,並且數據流將流過管道,然后將有效地執行下一個 pipe 運算符:

map(profiles => {
          const selectedProfile = profiles.findIndex(profile => profile.id === profileId);
          profiles[selectedProfile].canEdit = true;
            return profiles;
        })

暫無
暫無

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

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