Cách hủy đăng ký trong Angular2


81

Làm cách nào để hủy đăng ký trong Angular2? RxJS dường như có một phương thức xử lý, nhưng tôi không thể tìm ra cách truy cập nó. Vì vậy, tôi có mã có quyền truy cập vào EventEmitter và đăng ký nó, như thế này:

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

Tôi có thể sử dụng cách nào mySubscriptionđể hủy đăng ký?


2
FYI - nếu bạn định làm những việc Reactive, hãy sử dụng Chủ đề, thay vì EventEmitter của Angular - không có gì đảm bảo rằng nó sẽ vẫn là một lớp cha của Chủ thể. Chỉ sử dụng EventEmitter cho các sự kiện @Output.
robwormald

Câu trả lời:


121

Bạn đang tìm cách hủy đăng ký?

mySubscription.unsubscribe();

4
Chúa ơi. Tôi thề rằng tôi đã thử điều đó rồi. Tôi đã xem xét nguồn RxJS và đó dường như là những gì nó được. Tôi phải có một lỗi khác gây ra sự cố cho tôi. Cảm ơn.
Michael Oryl

1
điều này hoạt động tốt nhưng tôi tò mò không biết loại của mySubscriptionTypeScript là gì. Tôi muốn tránh viết mySubscription: anytrong lớp của mình.
paradite

11
@paradite import { Subscription } from "rxjs";và để hủy đăng ký if (!mySubscription.closed) { mySubscription.unsubscribe(); }.
Llyle

9
import { Subscription } from 'rxjs/Subscription';sẽ giúp giảm kích thước gói hàng của bạn
paul

50

Tôi nghĩ tôi cũng đã bỏ vào hai xu. Tôi sử dụng mẫu này:

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

BIÊN TẬP

Tôi đã đọc tài liệu một ngày nọ và tìm thấy một mô hình được khuyến nghị hơn:

ReactiveX / RxJS / Đăng ký

Ưu điểm:

Nó quản lý các đăng ký mới trong nội bộ và thêm một số kiểm tra gọn gàng. Thích phương pháp này trong tính năng :).

Nhược điểm:

Không rõ ràng 100% quy trình mã là gì và đăng ký bị ảnh hưởng như thế nào. Cũng không rõ ràng (chỉ bằng cách nhìn vào mã) nó xử lý như thế nào với các đăng ký đã đóng và nếu tất cả các đăng ký sẽ bị đóng nếu hủy đăng ký được gọi.

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

2
Tôi cũng sử dụng điều này, nó sẽ tăng tỷ lệ độc đáo khi bạn có nhiều đăng ký hơn trong một thành phần.
Weltschmerz

1
Không có gì "ma thuật" - đó là do thiết kế: "Các đăng ký cũng có thể được ghép lại với nhau, do đó, lệnh gọi hủy đăng ký () của một Đăng ký có thể hủy đăng ký nhiều Đăng ký. Bạn có thể làm điều này bằng cách" thêm "một đăng ký vào một đăng ký khác:" github. com / ReactiveX / rxjs / blob / master / doc / subscription.md
Meetai.com

Có một cách tiếp cận rõ ràng khác mà bạn có thể quan tâm. Sử dụng takeWhiletoán tử. Phương pháp mô tả ở đây: brianflove.com/2016/12/11/anguar-2-unsubscribe-observables
vdshb

Kiểm tra một giải pháp thay thế , đó là sử dụng takeUntil. Có một cuộc thảo luận phong phú và thú vị, xem xét các lựa chọn khác nhau.
Alex Klaus

8

CHỈNH SỬA: Điều này không áp dụng cho RxJS 5, đó là những gì angle2 đang sử dụng.

Tôi sẽ nghĩ rằng bạn đang tìm kiếm phương pháp xử lý trên Dùng một lần .

phương thức đăng ký trả về dùng một lần ( liên kết )

Tôi dường như không thể tìm thấy nó rõ ràng hơn trong tài liệu, nhưng điều này hoạt động ( jsbin ):

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

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

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

Thật kỳ lạ, việc hủy đăng ký dường như có hiệu quả với bạn trong khi nó không hiệu quả với tôi ...


Bạn có thể sử dụng các phiên bản khác nhau. Angular2 có trên Rxjs5 phải không?
user3743222 23/12/15

Có, góc 2 sử dụng RxJS 5.
Michael Oryl

1
Đó là nó. Có thể được tìm thấy ở đây . Sự thay đổi đã được thực hiện tuân thủ các ES7 Quan sát Spec
Niklas Fasching

4

Có quá nhiều lời giải thích khác nhau về việc hủy đăng ký trên Observables cho ng2, tôi đã mất nhiều thời gian để tìm ra câu trả lời đúng. Dưới đây là một ví dụ hoạt động (tôi đã cố gắng điều chỉnh tốc độ di chuyển chuột).

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


2
ngOnDestroy(){
   mySubscription.unsubscribe();
}

Ưu tiên hủy đăng ký rxjs hủy đăng ký trong khi hủy thành phần, tức là xóa khỏi DOM để tránh rò rỉ bộ nhớ không cần thiết


2

Cá nhân tôi thích sử dụng Chủ đề để đóng tất cả các đăng ký mà một thành phần có thể có ở bước hủy vòng đời có thể đạt được theo cách này:

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

2

Cách tiếp cận được khuyến nghị là sử dụng các toán tử RxJS như toán tử takeUntil . Dưới đây là đoạn mã hiển thị cách sử dụng nó: -

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

Bạn có thể tìm thấy lời giải chi tiết của chủ đề tại đây


tại sao chúng ta cần gọi ngUnsubscribe.next (); trong phương thức ngOnDestroy ()?
Biswa Bandhu Bhandary

1

Sử dụng

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

1
Trên thực tế nên làif (!mySubscription.closed) { mySubscription.unsubscribe(); }
Llyle

-1
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();
     }
`}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.