RxJS -- Subscription

solenovex發表於2018-03-28

Subscription是什麼?

當subscribe一個observable的時候, 返回的就是一個subscription. 它是一個一次性物件(disposable), 它有一個非常重要的方法 ubsubscribe(), 它沒有引數, 它會dispose掉subscription所持有的資源, 或者叫取消observable的執行.

第一個例子:

import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";
import 'rxjs/add/observable/interval';

const observable = Observable.interval(1000);

const subscription = observable.subscribe(x => console.log(x));

console.log(subscription);

subscription.unsubscribe();

console.log(subscription);

 

執行結果是這樣的:

Subscriber {
  closed: false,
  _parent: null,
  _parents: null,
  _subscriptions: 
   [ AsyncAction {
       closed: false,
       _parent: [Circular],
       _parents: null,
       _subscriptions: null,
       scheduler: [AsyncScheduler],
       work: [Function],
       pending: true,
       state: [Object],
       delay: 1000,
       id: [Timeout] } ],
  syncErrorValue: null,
  syncErrorThrown: false,
  syncErrorThrowable: false,
  isStopped: false,
  destination: 
   SafeSubscriber {
     closed: false,
     _parent: null,
     _parents: null,
     _subscriptions: null,
     syncErrorValue: null,
     syncErrorThrown: false,
     syncErrorThrowable: false,
     isStopped: false,
     destination: 
      { closed: true,
        next: [Function: next],
        error: [Function: error],
        complete: [Function: complete] },
     _parentSubscriber: [Circular],
     _context: [Circular],
     _next: [Function],
     _error: undefined,
     _complete: undefined } }
Subscriber {
  closed: true,
  _parent: null,
  _parents: null,
  _subscriptions: null,
  syncErrorValue: null,
  syncErrorThrown: false,
  syncErrorThrowable: false,
  isStopped: true,
  destination: 
   SafeSubscriber {
     closed: false,
     _parent: null,
     _parents: null,
     _subscriptions: null,
     syncErrorValue: null,
     syncErrorThrown: false,
     syncErrorThrowable: false,
     isStopped: false,
     destination: 
      { closed: true,
        next: [Function: next],
        error: [Function: error],
        complete: [Function: complete] },
     _parentSubscriber: [Circular],
     _context: [Circular],
     _next: [Function],
     _error: undefined,
     _complete: undefined } }

注意兩次控制檯輸出的closed屬性的值是不同的, true表示已經unsubscribe()了.

在ubsubscribe之後, _subscriptions屬性也變成空了, 之前它是一個陣列, 說明subscription可以是多個subscriptions的組合.

毀滅函式

如果使用Observable.create方法的話, 它的引數函式可以返回一個function. 而subscription在unsubscribe這個observable的時候, 會呼叫這個引數函式返回的function, 看例子:

import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";
import 'rxjs/add/observable/interval';

const observable = Observable.create(observer => {

    let index = 1;
    setInterval(() => {
        observer.next(index++);
    }, 200);

    return () => {
        // 在這可以做清理工作
        console.log('我在Observable.create返回的function裡面...');
    };
});

const subscription = observable.subscribe(
    x => console.log(x),
    err => console.error(err),
    () => console.log(`complete..`)
);

setTimeout(() => {
    subscription.unsubscribe();
}, 1100);

 

執行結果:

這個例子很好的解釋了我寫的那一堆拗口的解釋..

 

retry, retryWhen的原理

直接舉例:

import { Observable } from "rxjs/Observable";
import { Subscription } from "rxjs/Subscription";
import 'rxjs/add/observable/interval';
import 'rxjs/add/operator/retry';

const observable = Observable.create(observer => {

    setInterval(() => {
        observer.next('doing...');
        observer.error('error!!!');
    }, 200);

    return () => {
        // 在這可以做清理工作
        console.log('我在Observable.create返回的function裡面...');
    };
}).retry(4);

observable.subscribe(
    x => console.log(x),
    err => console.error(err),
    () => console.log(`complete..`)
);

 

可以看到, 每次執行next之後都會有錯誤, 重試4次.

執行結果:

可以看到, retry/retryWhen其實的原理即是先unsubscribe然後再重新subscribe而已, 所以每次retry都會執行我所稱的毀滅函式.

 

操作多個Subscriptions

多個subscriptions可以一起操作, 一個subscription可以同時unsubscribe多個subscriptions, 使用add方法為subscription新增另一個subscription. 對應的還有一個remove方法.

直接舉官網的例子:

var observable1 = Observable.interval(400);
var observable2 = Observable.interval(300);

var subscription = observable1.subscribe(x => console.log('first: ' + x));
var childSubscription = observable2.subscribe(x => console.log('second: ' + x));

subscription.add(childSubscription);

setTimeout(() => {
  // Unsubscribes BOTH subscription and childSubscription
  subscription.unsubscribe();
}, 1000);

 

執行結果:

 

相關文章