提问者:小点点

组件中的Angular 2重复订阅


除了在ngOnDestroy中取消订阅之外,还有什么方法可以避免组件中行为主题的重复订阅吗?到目前为止,这是我在一个组件上来回导航时发现的避免重复订阅的唯一方法,我在其中创建了一个可观察的订阅。

示例:

用户服务

@Injectable()
export class UserService {

  constructor(private http: Http) {
    this.setCurrentUser();
  }

  private currentUser$ = new BehaviorSubject<User>(null);

  public getCurrentUser(): Observable<User> {
    return this.currentUser$.asObservable();
  }
  public setCurrentUser(): void {
    this.getLoggedUser(); // 
  }


  private getLoggedUser(): void {

    let getCurrentUserUrl = 'http://127.0.0.1:8000/users/current/'

    let headers = new Headers({
      'Content-Type': 'application/json'
    });
    let options = new RequestOptions({
      headers: headers
    });
    options.withCredentials = true;

    this.http.get(getCurrentUserUrl, options)
      .map(this.toUser)
      .catch(this.handleError)
      .subscribe(
        user => this.currentUser$.next(user),
        error => console.log("Error subscribing to currentUser: " + error)
      );

  }

  private toUser(res: Response): User {
    let body = res.json();
    return body || { };
  }

}

以及从用户服务订阅可观察对象的组件…

export class AppComponent implements OnInit, OnDestroy {

  currentUserSubscription:any;

  constructor(
    private userService:UserService,
    private authentificationService:AuthenticationService
  ) {}

  user:User;

  ngOnInit() {
    this.currentUserSubscription =  this.userService.getCurrentUser().subscribe(
      data => {
        this.user = data;
        console.log('Main : ', this.user);
      }
    );
  }

  ngOnDestroy() {
    // I want to avoid writing this for every subscription
    this.currentUserSubscription.unsubscribe();
  }

}

如果我多次导航到组件,它会多次创建和销毁。订阅每次都随着组件初始化而创建,并且必须随着组件一起销毁。如果没有,它将在下一次组件初始化时重复…

有没有办法避免ngOnDestroy中的清理订阅?


共2个答案

匿名用户

如果您只想订阅一次,则需要在模板上使用异步管道,异步管道将自动管理取消订阅。如果您喜欢这种方法,您需要使用智能组件和演示组件组合您的应用程序。检查此答案

取消订阅的另一种方法是创建一个主题,这样订阅将完成,直到主题发出一个值。您应该始终取消订阅,否则您将出现内存泄漏。

export class AppComponent implements OnInit, OnDestroy {

  currentUserSubscription:any;

  constructor(
    private userService:UserService,
    private authentificationService:AuthenticationService,
    private _destroy : Subject() = new Subject();
  ) {}

  user:User;

  ngOnInit() {
    this.currentUserSubscription =  this.userService.getCurrentUser()
    .takeUntil(this._destroy)
    .subscribe(
      data => {
        this.user = data;
        console.log('Main : ', this.user);
      }
    );
  }

  ngOnDestroy() {
    this._destroy.next();
    this._destroy.unsubscribe();
  }

}

匿名用户

对于Angular 8,这解决了我的问题,我从许多组件订阅,并且只想从一个组件中删除一个订阅的一个观察者。这种模式将防止订阅重复并保存在其他活动组件中创建的订阅。

将订阅声明为组件中的对象:

sub: Subscription;

constructor(private userService: UserService) {
}

ngOnInit() {

 this.sub = this.userService.user.subscribe(user => this.subscription(user));
}

subscription(user) {
// do whatever you want during notification
}

ngOnDestroy() {
  this.sub.unsubscribe();
}