RxJs 6於2018年4月24日正式發佈,爲開發人員帶來了一些使人興奮的增補和改進。Ben Lesh, rxJS核心開發成員,強調:javascript
RxJs 6這些新的改動爲開發人員提供瞭如下三方面的優化:模塊化方面的改進、性能提高、調試更方便。RxJs團隊盡力保持新版本的向後兼容性,可是爲了減小RxJs的API數量,仍是引入了一些重大修改。java
下面讓咱們一塊兒來看一下RxJs團隊在新版本中引入了哪些修改。git
爲了便捷地從RxJS 5遷移到RxJS 6,RxJS團隊發佈了一個名爲rxjs-compa
t的兄弟軟件包。該軟件包在v6
和v5
的API之間建立了一個兼容層。
RxJs團隊建議開發人員經過安裝^6.0.0
版本的rxjs
和rxjs-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
中未覆蓋:ajax
在極少數狀況下,您的代碼庫定義了它本身的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-compat
提供了V5
與v6
API間的臨時兼容層,實質上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
升級您的應用程序?
使用新的管道操做符語法替換舊有的鏈式操做。上一個操做符方法的結果會被傳遞到下一個操做符方法中。
不要移除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中不能直接使用,要訪問它,請使用操做符multicast
,publish
,publishReplay
和publishLast
。SubscribeOnObservable
在v6中不能直接使用,要訪問它,請使用操做符subscribeOn
resultSelector
Result Selectors是一項沒有被普遍使用甚至沒有文檔說明的RxJs特性,同時Result Selectors嚴重的增長了RxJs代碼庫的體積,所以RxJs團隊決定棄用或刪除他。
對於使用到該功能的開發人員,他們須要將esultSelector
參數替換爲外部代碼。
對於first()
, last()
這兩個函數,這些參數已被移除,在刪除rxjs-compat
以前務必升級代碼。
對於其餘擁有resultSelector
參數的函數,如mapping
操做符,該參數已被棄用,並
以其餘方式重寫。若是您移除rxjs-compat
,這些函數仍可正常工做,可是RxJs團隊聲明他們必須在v7版本發佈以前將其移除。
針對該狀況的更多詳情,請查閱RxJs文檔
Observable.if
and Observable.throw
Observable.if
已被iif()
取代,Observable.throw
已被throwError()
取代。您可以使用rxjs-tslint
將這些廢棄的成員方法修改成函數調用。
代碼示例以下:
// deprecated Observable.if(test, a$, b$); // use instead iif(test, a$, b$);
// deprecated Observable.throw(new Error()); //use instead throwError(new Error());
根據遷移指南,如下方法已被棄用或重構:
import { merge } from 'rxjs/operators'; a$.pipe(merge(b$, c$)); // becomes import { merge } from 'rxjs'; merge(a$, b$, c$);
import { concat } from 'rxjs/operators'; a$.pipe(concat(b$, c$)); // becomes import { concat } from 'rxjs'; concat(a$, b$, c$);
import { combineLatest } from 'rxjs/operators'; a$.pipe(combineLatest(b$, c$)); // becomes import { combineLatest } from 'rxjs'; combineLatest(a$, b$, c$);
import { race } from 'rxjs/operators'; a$.pipe(race(b$, c$)); // becomes import { race } from 'rxjs'; race(a$, b$, c$);
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到代碼庫中。所以請務必測試您的功能以確保您的終端用戶最終接受到相同的質量體驗。