[英]Angular 6 call subscribe() for Observable multiple times
我有兩個組件:NewItemComponent和ListComponent。 當我在相應的組件內創建新項目時,我會通知ListComponent,以便它可以刷新其數據模型:
export class NewItemComponent implements OnInit {
constructor(private itemService: ItemService, private notificationService: NotificationService) {
}
ngOnInit() {
}
createNewItem(item: Item) {
this.itemService.persist(item).subscribe((response: Item) => {
console.log(response);
this.notificationService.notifyNewItemHasBeenCreated(response);
});
}
}
export class ListComponent implements OnInit {
items: Item[];
constructor(private listService: ListService, private notificationService: NotificationService) {
}
ngOnInit() {
this.loadItems();
this.notificationService.item$.subscribe((item) => {
if (item != null) {
this.loadItems();
}
})
}
loadItems(){
this.istService.getItems().subscribe((data: Item[]) => {
this.items= data;
console.log(this.items);
});
}
}
@Injectable({
providedIn: 'root'
})
export class NotificationService {
private _item: BehaviorSubject<Item> = new BehaviorSubject<Item>(null);
public item$ = this._item.asObservable();
constructor() {
}
notifyNewItemHasBeenCreated(item: Item) {
this._item.next(item);
}
}
讓我擔心的是loadItems()多次調用subscribe() 。 可以嗎?還是有更好的方法根據通知重新獲取項目?
loadItems(){
this.listService.getItems().subscribe((data: Item[]) => {
this.items= data;
console.log(this.items);
});
}
ListService返回Observable:
export class ListService {
basePath = 'my-api.com';
apiPath = "item";
constructor(private httpClient: HttpClient) {
}
getItems(): Observable<Item[]> {
return this.httpClient.get<Item[]>(this.basePath + '/' + this.apiPath);
}
}
在此先感謝您,任何幫助將不勝感激。
作為實驗,如果您執行以下操作:
this.httpClient.get("<some url>")
.subscribe({
next: () => {
console.log("received response")
},
error: err => {
console.log("error occurred")
},
complete: () => {
console.log("subscription completed")
},
})
您應該看到:
received response
subscription completed
這意味着在請求完成后,每個Web請求的可觀察對象都已完成,因此可以安全地取消訂閱,因為這是在可觀察對象完成時自動完成的。
編輯:
環顧四周后,我發現了這些帖子:
是否需要退訂Http方法創建的可觀察對象?
防止Angular 2中的內存泄漏?
注釋和答案解釋了HttpClient.get()
訂閱在其自身清除后HttpClient.get()
清除,因此您無需取消訂閱。 這意味着可以多次調用.subscribe()
。
如果您多次訂閱電話,則在銷毀組件時取消訂閱。
像這樣更改組件:
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
export class ListComponent implements OnInit, OnDestroy {
items: Item[];
constructor(private listService: ListService, private notificationService: NotificationService) {
}
subscriptions: Subscription[] = [];
ngOnInit() {
this.subscriptions.push(this.loadItems());
this.subscriptions.push(this.notificationService.item$.subscribe((item) => {
if (item) {
this.loadItems();
}
}));
}
ngOnDestroy() {
this.subscriptions.forEach(x => x.unsubscribe());
}
loadItems(){
this.istService.getItems().subscribe((data: Item[]) => {
this.items= data;
console.log(this.items);
});
}
}
loadItems()
調用僅subscribe
一次。
實際發生的情況是,您在notificationService.item$
的訂閱中多次調用loadItems()
。
如果您僅出於此目的需要NotificationService
,那么建議您少進行重構。
new-item.component.ts
export class NewItemComponent {
constructor(private itemService: ItemService, private listService: ListService) {
}
createNewItem(item: Item) {
this.itemService.persist(item).subscribe((response: Item) => {
this.listService.addItem(item);
});
}
}
list.service.ts
export class ListService {
basePath = 'my-api.com';
apiPath = 'item';
private itemsSubject: BehaviorSubject<Item[]> = new BehaviorSubject<Item[]>([]);
private items$: Observable<Item[]>;
constructor(private httpClient: HttpClient) {
}
getItems(): Observable<Item[]> {
const http$ = this.httpClient.get<Item[]>(this.basePath + '/' + this.apiPath);
return combineLatest(http$, this.items$).pipe(
map(([httpResponse: Item[], localItems: Item[]]) => httpResponse.concat(localItems)),
);
}
addItem(item: Item) {
this.itemsSubject.next([...this.itemsSubject.value, item]);
}
}
您現在正在做的是:
簡而言之,對於每個新項目,您都會向服務器發出2個請求,並獲得2個響應。
您可以看到這里有很多冗余。 讓我們嘗試簡化事情:
現在,您每次只發出一個請求,而不是兩個。 而且您不再需要處理那么多的Observable。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.