【问题标题】:How to cancel a subscription in Angular2如何在 Angular2 中取消订阅
【发布时间】:2016-03-30 07:15:42
【问题描述】:

如何在 Angular2 中取消订阅? RxJS 似乎有一个 dispose 方法,但我不知道如何访问它。所以我有可以访问 EventEmitter 并订阅它的代码,如下所示:

var mySubscription = someEventEmitter.subscribe(
    (val) => {
        console.log('Received:', val);
    },
    (err) => {
        console.log('Received error:', err);
    },
    () => {
        console.log('Completed');
    }
);

如何使用mySubscription取消订阅?

【问题讨论】:

  • 仅供参考 - 如果你要做响应式的事情,请使用 Subject,而不是 Angular 的 EventEmitter - 不能保证它仍然是 Subject 的超类。仅将 EventEmitter 用于 @Output 事件。

标签: javascript angular rxjs


【解决方案1】:

您要退订吗?

mySubscription.unsubscribe();

【讨论】:

  • 天哪。我发誓我已经试过了。我查看了 RxJS 源代码,它似乎就是这样。我一定有一个不同的错误导致我的问题。谢谢。
  • 这很好,但我很好奇 TypeScript 中 mySubscription 的类型是什么。我想避免在课堂上写mySubscription: any
  • @paradite import { Subscription } from "rxjs"; 和取消订阅if (!mySubscription.closed) { mySubscription.unsubscribe(); }
  • import { Subscription } from 'rxjs/Subscription'; 将帮助您缩小包裹尺寸
【解决方案2】:

我想我也投入了两分钱。我使用这种模式:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'my-component',
    templateUrl: 'my.component.html'
})
export class MyComponent implements OnInit, OnDestroy {

    private subscriptions: Array<Subscription> = [];

    public ngOnInit(): void {
        this.subscriptions.push(this.someService.change.subscribe(() => {
            [...]
        }));

        this.subscriptions.push(this.someOtherService.select.subscribe(() => {
            [...]
        }));
    }

    public ngOnDestroy(): void {
        this.subscriptions.forEach((subscription: Subscription) => {
            subscription.unsubscribe();
        });
    }
}

编辑

前几天我阅读了文档,发现了一个更推荐的模式:

ReactiveX/RxJS/Subscription

优点:

它在内部管理新订阅并添加了一些简洁的检查。在功能中更喜欢这种方法:)。

缺点:

目前还不是 100% 清楚代码流是什么以及订阅如何受到影响。也不清楚(仅通过查看代码)它如何处理已关闭的订阅以及如果调用 unsubscribe 是否所有订阅都将关闭。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';

@Component({
    selector: 'my-component',
    templateUrl: 'my.component.html'
})
export class MyComponent implements OnInit, OnDestroy {

    private subscription: Subscription = new Subscription();

    public ngOnInit(): void {
        this.subscription.add(this.someService.change.subscribe(() => {
            [...]
        }));

        this.subscription.add(this.someOtherService.select.subscribe(() => {
            [...]
        }));
    }

    public ngOnDestroy(): void {
        /*
         * magic kicks in here: All subscriptions which were added
         * with "subscription.add" are canceled too!
         */
        this.subscription.unsubscribe();
    }
}

【讨论】:

【解决方案3】:

编辑:这不适用于 angular2 正在使用的 RxJS 5。

我还以为你正在寻找 Disposable 上的 dispose 方法。

subscribe 方法返回一个 Disposable (link)

我似乎无法在文档中更明确地找到它,但这有效 (jsbin):

var observable = Rx.Observable.interval(100);

var subscription = observable.subscribe(function(value) {
   console.log(value);
});

setTimeout(function() {
  subscription.dispose();           
}, 1000)

奇怪的是,取消订阅似乎对你有用,而对我却不起作用......

【讨论】:

  • 您可能使用不同的版本。 Angular2 在 Rxjs5 上不是吗?
  • 是的,Angular 2 使用 RxJS 5。
  • 就是这样。可以找到here。进行更改以符合ES7 Observable Spec
【解决方案4】:

在 Observables for ng2 上取消订阅的解释太多了,我花了很长时间才找到正确的答案。下面是一个工作示例(我试图限制 mousemove)。

import {Injectable, OnDestroy} from "@angular/core";
import {Subscription} from "rxjs";

@Injectable()
export class MyClass implements OnDestroy {
  
  mouseSubscription: Subscription; //Set a variable for your subscription
  
  myFunct() {
    // I'm trying to throttle mousemove
    const eachSecond$ = Observable.timer(0, 1000);
    const mouseMove$ = Observable.fromEvent<MouseEvent>(document, 'mousemove');
    const mouseMoveEachSecond$ = mouseMove$.sample(eachSecond$);
    
    this.mouseSubscription = mouseMoveEachSecond$.subscribe(() => this.doSomethingElse());
  }

  doSomethingElse() {
    console.log("mouse moved");
  }
  
  stopNow() {
    this.mouseSubscription.unsubscribe();
  }
  
  ngOnDestroy() {
    this.mouseSubscription.unsubscribe();
  }
  
}

【讨论】:

    【解决方案5】:
    ngOnDestroy(){
       mySubscription.unsubscribe();
    }
    

    最好在销毁组件时取消订阅 rxjs 取消订阅,即从 DOM 中删除以避免不必要的内存泄漏

    【讨论】:

      【解决方案6】:

      我个人更喜欢使用 Subject 来关闭组件在销毁生命周期步骤中可能拥有的所有订阅,这可以通过这种方式实现:

      import { Component} from '@angular/core';
      import { Subject } from "rxjs/Rx";
      
      @Component({
        selector:    'some-class-app',
        templateUrl: './someClass.component.html',
        providers:   []
      })
      
      export class SomeClass {  
      
        private ngUnsubscribe: Subject<void> = new Subject<void>(); //This subject will tell every subscriptions to stop when the component is destroyed.
      
        //**********
        constructor() {}
      
        ngOnInit() {
      
          this.http.post( "SomeUrl.com", {}, null ).map( response => {
      
            console.log( "Yay." );
      
          }).takeUntil( this.ngUnsubscribe ).subscribe(); //This is where you tell the subscription to stop whenever the component will be destroyed.
        }
      
        ngOnDestroy() {
      
          //This is where we close any active subscription.
          this.ngUnsubscribe.next();
          this.ngUnsubscribe.complete();
        }
      }
      

      【讨论】:

        【解决方案7】:

        推荐的方法是使用 RxJS 运算符,例如 takeUntil 运算符。下面是代码 sn-p 显示如何使用它:-

        import { Component, OnInit, OnDestroy } from '@angular/core';
        import { interval, Subject } from 'rxjs';
        import { takeUntil } from 'rxjs/operators';
        
        @Component({
            selector: 'app-root',
            templateUrl: './app.component.html'
        })
        export class AppComponent implements OnInit, OnDestroy {
            private ngUnsubscribe = new Subject();
        
            constructor() { }
        
            ngOnInit() {
                var observable1 = interval(1000);
                var observable2 = interval(2000);
        
                observable1.pipe(takeUntil(this.ngUnsubscribe)).subscribe(x => console.log('observable1: ' + x));
                observable2.pipe(takeUntil(this.ngUnsubscribe)).subscribe(x => console.log('observable2: ' + x));
            }
        
            ngOnDestroy() {
                this.ngUnsubscribe.next();
                this.ngUnsubscribe.complete();
            }
        }
        

        可以找到题目的详细解释here

        【讨论】:

        • 为什么我们需要调用 ngUnsubscribe.next();在 ngOnDestroy() 方法中?
        【解决方案8】:

        使用

        if(mySubscription){
          mySubscription.unsubscribe();
        }
        

        【讨论】:

        • 其实应该是if (!mySubscription.closed) { mySubscription.unsubscribe(); }
        【解决方案9】:
        import { Subject } from 'rxjs';
        import { takeUntil } from 'rxjs/operators';
        import { SomeAPIService } from '../some_file/someAPIService.service.ts
        
        @Component({
          templateUrl: './your_Page.html',
          styleUrls: ['./your_Styles.scss']
        })
        
        export class (your class) implements OnInit, OnDestroy {
           // This is a subject variable at it simplest form 
             private unsubscribe$ = new Subject<void>();
        
             constructor (private someAPIService : SomeAPIService) {}
           
             ngOnit(): void { 
               this.someAPIService.getTODOlist({id:1})
                .pipe(takeUntil(this.unsubscribe$))
                 .subscribe((value: SomeVariable) => {
                 // What ever value you need is SomeVariable
              },)
            }
        
        
             ngOnDestroy(): void {
            // clears all, page subscriptions 
              this.unsubscribe$.next();
              this.unsubscribe$.complete();
             }
        `}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-13
          • 2017-09-14
          • 2022-01-19
          • 2012-03-14
          • 1970-01-01
          • 2017-04-13
          • 2018-02-07
          • 2019-12-05
          相关资源
          最近更新 更多