RxJS操作符(二)

starof發表於2018-06-05

一、Observable的性質

三種狀態:nex, error, complete

 

進入到Error狀態:

const interval$ = Rx.Observable.interval(1000)
.filter(val=>{
  throw '出錯了'
})
.take(4)
.reduce((x,y)=>{//reduce接收函式作為引數
  return [...x,y];
},[])

interval$.subscribe(
  val=>console.log(val),
  err=>console.error('Error:' + err),
  ()=>console.log('I am complete')
);

 

 

二、特殊型別的Observable

  • 永不結束
  • Never
  • Empty
  • Throw

永不結束:沒有complete狀態,比如計時器,每隔1s發射item。

Never:完全不發射item,也不結束。【測試時幫助構成條件】

const interval$ = Rx.Observable.never();
//不會emit任何元素,也不會結束

interval$.subscribe(
  val=>console.log(val),
  err=>console.error('Error:' + err),
  ()=>console.log('I am complete')
);
View Code

 

Empty:流裡沒有元素,直接進入Complete狀態。

const interval$ = Rx.Observable.empty(); //不會輸出任何元素,直接結束

interval$.subscribe(
  val=>console.log(val),
  err=>console.error('Error:' + err),
  ()=>console.log('I am complete')
);
View Code

 

Throw:不發生任何東西,直接進入Error狀態。 

const interval$ = Rx.Observable.throw('出錯了');

interval$.subscribe(
  val=>console.log(val),
  err=>console.error('Error:' + err),
  ()=>console.log('I am complete')
);
View Code

 

三、工具類操作符do

一般用來做除錯。

或者外部條件的設定。

流進入到下一步之前需要對外部的東西進行改變【寫檔案之類】

const interval$ = Rx.Observable.interval(1000)
.map(val=>val*2)
.do(v=>console.log('val is' +v))   //在map之後,take之前,在流發生之前看一下流裡有什麼東西
.take(3);
interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

do很像臨時subscribe,但是沒有把流中斷掉。可以繼續應用操作符。臨時中間橋樑,列印值做除錯。

let logLabel='當前值是';

const interval$ = Rx.Observable.interval(1000)
.map(val=>val*2)
.do(v=>{
       console.log(logLabel +v); //取得了外部的值
       logLabel='當前'; //改變了外部的值
})
.take(4);

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

 

四、變換類操作符:scan

scan:

場景:記住之前的運算結果。每次運算都會發射值。

scan接收函式作為引數,x是增加器,預設初始值0,把函式返回的結果作為下次的x。

const interval$ = Rx.Observable.interval(1000)
.filter(val=>val%2===0)
.scan((x,y)=>{//scan接收函式作為引數
  return x+y;
})
.take(4)

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

 

五、數學類操作符reduce

陣列中也有,使用比較頻繁。

和scan對比,reduce只會發射一個最終值。

.filter(val=>val%2===0)
.take(4)
.reduce((x,y)=>{//reduce接收函式作為引數,只會發射一個最後的值
  return x+y;
})

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

高階用法:

const interval$ = Rx.Observable.interval(1000)
.filter(val=>val%2===0)
.take(4)
.reduce((x,y)=>{//reduce接收函式作為引數
  return [...x,y];  //每次陣列加y
},[]) //x初始值為空陣列[]

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

 

六、過濾類操作符 filter,take,first/last,skip...

filter:

let logLabel='當前值是';

const interval$ = Rx.Observable.interval(1000)
.filter(val=>val%2===0)  //過濾偶數
.do(v=>{console.log(logLabel +v);
       logLabel='當前';}
)
.take(3);

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

first:

const interval$ = Rx.Observable.interval(1000)
.filter(val=>val%2===0)
.first()    //和take(1)是一樣的,取第一個
// .take(1) 

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

skip: 和take相反

const interval$ = Rx.Observable.interval(1000)
.filter(val=>val%2===0)
.skip(2); //過濾掉0和2

interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
); 

七、常見建立類操作符:Interval,Timer

1、interval

const interval$ = Rx.Observable.interval(1000);
interval$.subscribe(val=>console.log(val));

通過take取前3個來看三種狀態的效果

const interval$ = Rx.Observable.interval(1000).take(3);
interval$.subscribe(
  val=>console.log(val),
  err=>console.log(err),
  ()=>console.log('I am complete')
);

2、Timer

const timer$= Rx.Observable.timer(1000);

timer$.subscribe(v=>console.log(v));
//控制檯只輸出一個值0

第一個引數:delay多長時間

第二個引數:之後要以什麼頻率傳送

const timer$= Rx.Observable.timer(1000,1000);
timer$.subscribe(v=>console.log(v));
//類似interval,但是interval不能指定開始延遲時間

 

實踐:給Observable增加一個debug操作符

只有在生產環境才輸出

import {Observable} from 'rxjs/Observable';
import {environment} from '../../environments/environment';

declare module 'rxjs/Observable' {
  interface Observable<T> {
    debug: (...any) => Observable<T>;
  }
}

Observable.prototype.debug = function(message: string) {
  return this.do(
    (next) => {
      if (!environment.production) {
        console.log(message, next);
      }
    },
    (err) => {
      if (!environment.production) {
        console.error('ERROR>>>', message, err);
      }
    },
    () => {
      if (!environment.production) {
        console.log('Completed - ');
      }
    }
  );
};

 

 

本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載註明出處:https://www.cnblogs.com/starof/p/9137865.html 有問題歡迎與我討論,共同進步。

 

相關文章