【问题标题】:Angular 2 duplicated subscription in componentAngular 2在组件中重复订阅
【发布时间】:2017-06-02 06:07:28
【问题描述】:

除了在 ngOnDestroy 中取消订阅之外,有没有办法避免对组件中的 behaviorSubject 重复订阅?到目前为止,这是我发现在我在可观察对象上创建订阅的组件上来回导航时避免重复订阅的唯一方法。

例子:

用户服务

@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 || { };
  }

}

还有一个组件从用户服务订阅 observable...

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 中清理订阅?

【问题讨论】:

    标签: angular observable


    【解决方案1】:

    对于 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();
    }
    

    【讨论】:

      【解决方案2】:

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

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

      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();
        }
      
      }
      

      【讨论】:

      • 谢谢!我一直在寻找一个“直到被破坏”的解决方案。我不得不对主题的声明和初始化方式进行一些调整,但它可以工作。我来看看智能和演示组件的概念。
      • 你不应该nextunsubscribe。相反,只需这样做:complete :)
      猜你喜欢
      • 1970-01-01
      • 2017-04-19
      • 2016-10-09
      • 2018-06-04
      • 1970-01-01
      • 2018-10-17
      • 2018-06-12
      • 2021-12-14
      • 2019-01-25
      相关资源
      最近更新 更多