Angular2/4 取消订阅永不销毁的组件中的可观察对象
Angular2/4 unsubscribe observable in a component which never be destroyed
我是 Angular4 的新手。很抱歉这个基本问题和我糟糕的英语。我会尽力描述我的问题。
我现在正在开发一个使用可观察服务来共享消息的网站。
但是我遇到了一个问题,
这是我的 example file structure. and the working Plunker
.
我 "Header Component" 收到了来自 "User Component" 的消息。
Header 分量:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";
@Component({
selector: 'shared-header',
template: `<div class="my-header">
<span>This is header </span>
<span class="right-align">Recieve Data:{{received}}</span>
</div>`,
})
export class HeaderComponent implements OnInit, OnDestroy{
private subscription: Subscription;
private received = "none";
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.subscription = this.sharedService.shareAction$.subscribe(result => {
if(result){
this.received = result;
}
};
}
ngOnDestory(){
this.subscription.unsubscribe();
}
}
用户组件:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";
@Component({
selector: 'shared-header',
template: `<div class="my-header">
<span>This is header </span>
<span class="right-align">Recieve Data:{{received}}</span>
</div>`,
})
export class HeaderComponent implements OnInit, OnDestroy{
private subscription: Subscription;
private received = "none";
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.subscription = this.sharedService.shareAction$.subscribe(result => {
if(result){
this.received = result;
}
};
}
ngOnDestory(){
this.subscription.unsubscribe();
}
}
和 "Widget Component" 收到来自 "Product Component" 的消息。
小部件组件:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";
@Component({
selector: 'widget',
template: `<div>---Widget----</div>
<div>=={{productName}}==</div>`,
})
export class WidgetComponent implements OnInit, OnDestroy{
private productName = "none";
private subscription: Subscription;
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.subscription = this.sharedService.shareAction$.subscribe(result => {
if(result){
this.productName = result;
}
};
}
ngOnDestory(){
this.subscription.unsubscribe();
}
}
产品组件:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { SharedService } from "./sharedService";
@Component({
template: `<h4>This is ProductPage</h4>
<widget></widget>`,
})
export class ProductComponent implements OnInit, OnDestroy{
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.sharedService.publishData('NIKE');
}
}
我创建了一个 sharedService 来处理可观察的服务。
共享服务:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/subscription';
@Injectable()
export class SharedService {
private shareAction = new BehaviorSubject<any>(null);
shareAction$ = this.shareAction.asObservable()
sharedObject: object = {};
constructor() {}
publishData(data) {
console.log('publish------------------------------');
this.shareAction.next(data);
}
}
所以当点击"user page"时,header右侧的信息会显示"User Page"。
当点击 "Product page" 时,小部件下方的信息将显示 "NIKE"。但与此同时,header 信息也更改为 "NIKE",我不希望它发生。
我知道我应该在组件销毁时取消订阅,但在这种情况下,Header 永远不会被销毁。所以也许....我应该在 "user Component" 销毁时取消订阅,并在 "user Component" 初始化时再次订阅,但我不知道该怎么做,或者这个想法很糟糕。
请多指教,任何意见都会有所帮助。
非常感谢。
我认为问题在于您使用单个 shareAction$
来做太多事情。为什么不为 header 信息制作一个主题,为小部件制作另一个主题?
此外,shareAction$
过于宽泛:尝试给它起一个更具体的名称,例如 headerTitle$
和 currentProduct$
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/subscription';
@Injectable()
export class SharedService {
private headerTitle = new BehaviorSubject<string>(null);
headerTitle$ = this.headerTitle.asObservable();
private currentProduct = new BehaviorSubject<any>(null);
currentProduct$ = this.currentProduct.asObservable();
constructor() {}
setHeaderTitle(title:string):void {
this.headerTitle.next(title);
}
setCurrentProduct(product:any):void {
this.currentProduct.next(product);
}
}
这样,Header 组件和 Widget 组件都不需要知道何时 subscribe/unsubscribe:它们只需在创建时订阅,在销毁时取消订阅。
此外,请考虑避免将 any
作为类型:当您的应用程序足够大时,它会为您省去很多问题,因为如果有一些变化导致类型不匹配,编译器会告诉您有一些问题错了。
您是否需要 CurrentProduct
通过服务在全球范围内共享?如果您只在 Product 组件 - Widget 组件中使用它,也许通过组件参数传递它就足够了。
使用angular 2+内置机制(|异步),它会自动取消订阅。
some.component.ts:
this.heroes = this.heroService.getHeroes();
some.component.html:
<li *ngFor="let hero of heroes | async" (click)="selectedHero=hero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
我是 Angular4 的新手。很抱歉这个基本问题和我糟糕的英语。我会尽力描述我的问题。
我现在正在开发一个使用可观察服务来共享消息的网站。
但是我遇到了一个问题,
这是我的 example file structure. and the working Plunker
.
我 "Header Component" 收到了来自 "User Component" 的消息。
Header 分量:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";
@Component({
selector: 'shared-header',
template: `<div class="my-header">
<span>This is header </span>
<span class="right-align">Recieve Data:{{received}}</span>
</div>`,
})
export class HeaderComponent implements OnInit, OnDestroy{
private subscription: Subscription;
private received = "none";
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.subscription = this.sharedService.shareAction$.subscribe(result => {
if(result){
this.received = result;
}
};
}
ngOnDestory(){
this.subscription.unsubscribe();
}
}
用户组件:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";
@Component({
selector: 'shared-header',
template: `<div class="my-header">
<span>This is header </span>
<span class="right-align">Recieve Data:{{received}}</span>
</div>`,
})
export class HeaderComponent implements OnInit, OnDestroy{
private subscription: Subscription;
private received = "none";
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.subscription = this.sharedService.shareAction$.subscribe(result => {
if(result){
this.received = result;
}
};
}
ngOnDestory(){
this.subscription.unsubscribe();
}
}
和 "Widget Component" 收到来自 "Product Component" 的消息。
小部件组件:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { Subscription } from 'rxjs/subscription';
import { SharedService } from "./sharedService";
@Component({
selector: 'widget',
template: `<div>---Widget----</div>
<div>=={{productName}}==</div>`,
})
export class WidgetComponent implements OnInit, OnDestroy{
private productName = "none";
private subscription: Subscription;
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.subscription = this.sharedService.shareAction$.subscribe(result => {
if(result){
this.productName = result;
}
};
}
ngOnDestory(){
this.subscription.unsubscribe();
}
}
产品组件:
import { Component, OnInit, OnDestroy} from '@angular/core';
import { SharedService } from "./sharedService";
@Component({
template: `<h4>This is ProductPage</h4>
<widget></widget>`,
})
export class ProductComponent implements OnInit, OnDestroy{
constructor(private sharedService : SharedService) {}
ngOnInit(){
this.sharedService.publishData('NIKE');
}
}
我创建了一个 sharedService 来处理可观察的服务。 共享服务:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/subscription';
@Injectable()
export class SharedService {
private shareAction = new BehaviorSubject<any>(null);
shareAction$ = this.shareAction.asObservable()
sharedObject: object = {};
constructor() {}
publishData(data) {
console.log('publish------------------------------');
this.shareAction.next(data);
}
}
所以当点击"user page"时,header右侧的信息会显示"User Page"。 当点击 "Product page" 时,小部件下方的信息将显示 "NIKE"。但与此同时,header 信息也更改为 "NIKE",我不希望它发生。
我知道我应该在组件销毁时取消订阅,但在这种情况下,Header 永远不会被销毁。所以也许....我应该在 "user Component" 销毁时取消订阅,并在 "user Component" 初始化时再次订阅,但我不知道该怎么做,或者这个想法很糟糕。
请多指教,任何意见都会有所帮助。 非常感谢。
我认为问题在于您使用单个 shareAction$
来做太多事情。为什么不为 header 信息制作一个主题,为小部件制作另一个主题?
此外,shareAction$
过于宽泛:尝试给它起一个更具体的名称,例如 headerTitle$
和 currentProduct$
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/subscription';
@Injectable()
export class SharedService {
private headerTitle = new BehaviorSubject<string>(null);
headerTitle$ = this.headerTitle.asObservable();
private currentProduct = new BehaviorSubject<any>(null);
currentProduct$ = this.currentProduct.asObservable();
constructor() {}
setHeaderTitle(title:string):void {
this.headerTitle.next(title);
}
setCurrentProduct(product:any):void {
this.currentProduct.next(product);
}
}
这样,Header 组件和 Widget 组件都不需要知道何时 subscribe/unsubscribe:它们只需在创建时订阅,在销毁时取消订阅。
此外,请考虑避免将 any
作为类型:当您的应用程序足够大时,它会为您省去很多问题,因为如果有一些变化导致类型不匹配,编译器会告诉您有一些问题错了。
您是否需要 CurrentProduct
通过服务在全球范围内共享?如果您只在 Product 组件 - Widget 组件中使用它,也许通过组件参数传递它就足够了。
使用angular 2+内置机制(|异步),它会自动取消订阅。
some.component.ts:
this.heroes = this.heroService.getHeroes();
some.component.html:
<li *ngFor="let hero of heroes | async" (click)="selectedHero=hero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>