[英]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.