簡體   English   中英

為多個“可觀察的消費者”創建一個訂閱

[英]Create one subscription for multiple 'observable consumers'

經理state 為用戶提供本店服務。 在商店中,有一個“選擇”方法可以映射以獲取用戶 ID:

type User = { userId: number };

@Injectable({ providedIn: "root" })
export class SomeService {
  activeUsers$ = new BehaviorSubject<User[]>([]);

  selectUserIds = (): Observable<number[]> => {
    return this.activeUsers$
      .asObservable()
      .pipe(map((data) => data.map(({ userId }) => userId)));
  };
  // ...
}

在組件中,我調用該方法來查看哪個用戶處於活動狀態:

@Component({
  selector: "app-root",
  template: `
  <div>
    <h1>See console output</h1>
    <ng-container *ngFor="let user of users">
      <div [ngClass]="{'active': (activeUserIds$ | async).includes(user.userId)}">
        {{ user.userName }}
      </div>
    </ng-container>
  </div>`,
})
export class AppComponent implements OnInit {

  activeUserIds$: Observable<number[]>;

  users = [
    { userId: 1, userName: "John" },
    { userId: 2, userName: "Fred" },
    { userId: 3, userName: "Alex" }
  ];

  constructor(private someService: SomeService) {}

  ngOnInit(): void {
    this.activeUserIds$ = this.someService.selectUserIds().pipe(
      tap((data) => {
        console.log("data: ", data);
      }),
    );
  }
}

但是在控制台中,它發生在模板中被調用的次數(三次):

// console output:
// data: []
// data: []
// data: []

做三遍似乎是多余的。 但我確實希望它對 state 的更新做出反應。

我的想法是,通過在 OnInit 中創建“activeUserIds$”,我將擁有1 個可觀察對象並多次使用它。 但它似乎是多次訂閱。

只有 1 個訂閱的方法是什么?

沙盒鏈接: https://codesandbox.io/s/red-bird-n7xips?file=/src/app/app.component.ts

當您在*ngFor中使用async時,您正在創建三個訂閱。 它不知道activeUserIds$ | async activeUserIds$ | async將在您每次訂閱時發出相同的值。

一種解決方案是在模板中使用局部變量,並使用ngrxLet中的 ngrxLet 等指令僅訂閱一次。

在 vanilla Angular 中,最簡單的方法(沒有*ngIf和這個https://github.com/angular/angular/issues/15280 )可能是到 append shareReplay(1)take(1)到鏈中,以便它立即完成並不會訂閱源 Observable:

this.activeUserIds$ = this.someService.selectUserIds().pipe(
  tap((data) => {
    console.log("data: ", data);
  }),
  shareReplay(1),
  take(1),
);

現場演示: https://stackblitz.com/edit/angular-ivy-woypne?file=src%2Fapp%2Fapp.component.ts

暫無
暫無

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

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