RxJS 6有哪些新變化?

RxJS 6有哪些新變化?

RxJs 6於2018年4月24日正式發佈,爲開發人員帶來了一些使人興奮的增補和改進。Ben Lesh, rxJS核心開發成員,強調:javascript

  1. RxJS 6在擁有更小API的同時,帶來了更整潔的引入方式
  2. 提供一個npm包,該package能夠處理RxJS的向後兼容性,使得開發人員能夠在不更改代碼的狀況下進行更新,同時還能夠幫助TypeScript代碼自動遷移。

RxJs 6這些新的改動爲開發人員提供瞭如下三方面的優化:模塊化方面的改進、性能提高、調試更方便。RxJs團隊盡力保持新版本的向後兼容性,可是爲了減小RxJs的API數量,仍是引入了一些重大修改。java

下面讓咱們一塊兒來看一下RxJs團隊在新版本中引入了哪些修改。git

RxJS 6的向後兼容性

爲了便捷地從RxJS 5遷移到RxJS 6,RxJS團隊發佈了一個名爲rxjs-compat的兄弟軟件包。該軟件包在v6v5的API之間建立了一個兼容層。
RxJs團隊建議開發人員經過安裝^6.0.0版本的rxjsrxjs-compat包來升級現有應用:github

npm install rxjs@6 rxjs-compat@6 --save

此包容許您在升級RxJS 6的同時繼續運行現有代碼庫,而不會出現問題。他支持在RxJs 6中移除掉的功能。
安裝rxjs-compat會致使打包後代碼包體積的增長,若是你使用的是4.0.0版本如下的Webpack,該影響會被放大。
所以建議升級完成後將rxjs-compat移除。web

使用rxjs-compat升級RxJS的限制

只有兩個重大修改在rxjs-compat中未覆蓋:ajax

TypeScript原型操做符

在極少數狀況下,您的代碼庫定義了它本身的TypeScript原型操做符並修改了Observable命名空間。該狀況下,您須要更新你的操做符相關代碼才能使TypeScript正常編譯。npm

在版本發佈說明中,用戶自定義的原型操做符可按以下方式建立:bash

Observable.prototype.userDefined = () => {
  return new Observable((subscriber) => {
    this.subscribe({
      next(value) { subscriber.next(value); },
      error(err) { subscriber.error(err); },
      complete() { subscriber.complete(); },
   });
  });
});

source$.userDefined().subscribe();

爲編譯該類型的自定義操做符,須要作以下修改:websocket

const userDefined = <T>() => (source: Observable<T>) => new Observable<T>((subscriber) => {
    this.subscribe({
      next(value) { subscriber.next(value); },
      error(err) { subscriber.error(err); },
      complete() { subscriber.complete(); },
   });
  });
});

source$.pipe(
  userDefined(),
)

同步錯誤處理

再也不支持在try / catch塊內調用Observable.subscribe()。使用用Observable.subscribe()方法中的錯誤回調方法替換原先的try / catch塊來完成的異步錯誤的處理。
示例以下:session

// deprecated
try {
  source$.subscribe(nextFn, undefined, completeFn);
} catch (err) {
  handleError(err);
}

// use instead
source$.subscribe(nextFn, handleError, completeFn);

如今在Observable.subscribe()中必須定義一個錯誤回調方法來異步處理錯誤。

刪除RxJs兼容層前須要作的修改

如上所訴,rxjs-compat提供了V5v6API間的臨時兼容層,實質上rxjs-compat爲您的代碼庫提供了所需的v5版本功能,使得您能夠逐步將您的代碼庫升級到v6版本。爲了完成升級並移除rxjs-compat依賴,您的代碼庫須要重構並中止使用v5版本中的以下功能:

修改import路徑

建議TypeScript開發人員使用rxjs-tslint來重構import路徑。
RxJS團隊設計瞭如下規則來幫助JavaScript開發人員重構import路徑:

  • rxjs: 包含建立方法,類型,調度程序和工具庫。

    import { Observable, Subject, asapScheduler, pipe, of, from, interval, merge, fromEvent } from 'rxjs';
  • rxjs/operators: 包含全部的管道操做符

    import { map, filter, scan } from 'rxjs/operators';
  • rxjs/webSocket: 包含websocket subject實現.

    import { webSocket } from 'rxjs/webSocket';
  • rxjs/ajax: 包含Rx ajax實現.

    import { ajax } from 'rxjs/ajax';
  • rxjs/testing: 包含RxJS的測試工具庫.

    import { TestScheduler } from 'rxjs/testing';

如下是一項小調查:您是否有常識使用rxjs-tslint升級您的應用程序?
clipboard.png

使用管道操做而不是鏈式操做

使用新的管道操做符語法替換舊有的鏈式操做。上一個操做符方法的結果會被傳遞到下一個操做符方法中。
不要移除rxjs-compat包,直到你將全部的鏈式操做修改成管道操做符。若是您使用TypeScript, ts-lint會在某種程度上自動執行此項重構。
Ben Lesh在ng-conf 2018上解釋了爲何咱們應該使用管道操做符

請按照以下步驟將您的鏈式操做替換爲管道操做:

  • rxjs-operators中引入您須要的操做符

    注意:因爲與Javascript保留字衝突,如下運算符名字作了修改: do -> tap, catch ->
    catchError, switch -> switchAll, finally -> finalize
    import { map, filter, catchError, mergeMap } from 'rxjs/operators';
  • 使用pipe()包裹全部的操做符方法。確保全部操做符間的.被移除,轉而使用,鏈接。記住!!!有些操做符的名稱變了!!!
    如下爲升級示例:

    // an operator chain
    source
      .map(x => x + x)
      .mergeMap(n => of(n + 1, n + 2)
        .filter(x => x % 1 == 0)
        .scan((acc, x) => acc + x, 0)
      )
      .catch(err => of('error found'))
      .subscribe(printResult);
    
    // must be updated to a pipe flow
    
    source.pipe(
      map(x => x + x),
      mergeMap(n => of(n + 1, n + 2).pipe(
        filter(x => x % 1 == 0),
        scan((acc, x) => acc + x, 0),
      )),
      catchError(err => of('error found')),
    ).subscribe(printResult);

    注意咱們在以上代碼中嵌套使用了pipe()

使用函數而不是類

使用函數而不是類來操做可觀察對象(Observables)。全部的Observable類已被移除。他們的功能被新舊操做符及函數替代。這些替代品的功能與以前的類功能如出一轍。
示例以下:

// removed
ArrayObservable.create(myArray)

// use instead

from(myArray)

// you may also use

new operator fromArray().

有關替換v5類爲v6函數的完整列表,請查看RxJS文檔

特殊狀況

  • ConnectableObservable在v6中不能直接使用,要訪問它,請使用操做符multicastpublishpublishReplaypublishLast
  • SubscribeOnObservable在v6中不能直接使用,要訪問它,請使用操做符subscribeOn

移除resultSelector

Result Selectors是一項沒有被普遍使用甚至沒有文檔說明的RxJs特性,同時Result Selectors嚴重的增長了RxJs代碼庫的體積,所以RxJs團隊決定棄用或刪除他。

對於使用到該功能的開發人員,他們須要將esultSelector參數替換爲外部代碼。

對於first(), last()這兩個函數,這些參數已被移除,在刪除rxjs-compat以前務必升級代碼。

對於其餘擁有resultSelector參數的函數,如mapping操做符,該參數已被棄用,並
以其餘方式重寫。若是您移除rxjs-compat,這些函數仍可正常工做,可是RxJs團隊聲明他們必須在v7版本發佈以前將其移除。

針對該狀況的更多詳情,請查閱RxJs文檔

其餘RxJs6棄用

Observable.if and Observable.throw

Observable.if已被iif()取代,Observable.throw已被throwError()取代。您可以使用rxjs-tslint將這些廢棄的成員方法修改成函數調用。

代碼示例以下:

OBSERVABLE.IF > IIF()

// deprecated
Observable.if(test, a$, b$);

// use instead

iif(test, a$, b$);

OBSERVABLE.ERROR > THROWERROR()

// deprecated
Observable.throw(new Error());

//use instead

throwError(new Error());

已棄用的方法

根據遷移指南,如下方法已被棄用或重構:

merge

import { merge } from 'rxjs/operators';
a$.pipe(merge(b$, c$));

// becomes

import { merge } from 'rxjs';
merge(a$, b$, c$);

concat

import { concat } from 'rxjs/operators';
a$.pipe(concat(b$, c$));

// becomes

import { concat } from 'rxjs';
concat(a$, b$, c$);

combineLatest

import { combineLatest } from 'rxjs/operators';
a$.pipe(combineLatest(b$, c$));

// becomes

import { combineLatest } from 'rxjs';
combineLatest(a$, b$, c$);

race

import { race } from 'rxjs/operators';
a$.pipe(race(b$, c$));

// becomes

import { race } from 'rxjs';
race(a$, b$, c$);

zip

import { zip } from 'rxjs/operators';
a$.pipe(zip(b$, c$));

// becomes

import { zip } from 'rxjs';
zip(a$, b$, c$);

總結

RxJS 6帶來了一些重大改變,可是經過添加rxjs-compat軟件包能夠緩解這一問題,該軟件包容許您在保持v5代碼運行的同時逐漸遷移。對於Typescript用戶,其餘中包括大多數Angular開發人員,tslint提供了大量的自動重構功能,使轉換變得更加簡單。

任何升級與代碼修改都會引入一些bug到代碼庫中。所以請務必測試您的功能以確保您的終端用戶最終接受到相同的質量體驗。

視頻:RxJS 6詳細介紹 by Ben Lesh

原文連接

相關文章
相關標籤/搜索