W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
RxJS v6 到了! 盡管這是主要的版本更改(從 5.x 更改為 6.x), 我們已經(jīng)進(jìn)行了大量工作,以將艱巨的更改保持在最低限度。 在大多數(shù)情況下,這允許應(yīng)用程序和庫開發(fā)人員逐步更新 并使用 RxJS v6,無需對(duì)其代碼進(jìn)行任何修改。
向后兼容層簡化了更新過程,使您可以保持 應(yīng)用程序在您按自己的進(jìn)度處理大多數(shù)代碼更改時(shí)仍在運(yùn)行。 整個(gè)過程可以分階段進(jìn)行:
rxjs-compat
。 rxjs-compat
的影響,請(qǐng)根據(jù)下面提供的說明更新受影響的代碼。
要重構(gòu) TypeScript 代碼,使其不依賴于 rxjs-compat,可以使用 rxjs-tslint
。
npm i -g rxjs-tslint
rxjs-5-to-6-migrate -p [path/to/tsconfig.json]
為了最大程度地減少升級(jí)的影響,RxJS v6 發(fā)行了一個(gè)同級(jí)軟件包 軟件包 rxjs-compat
,該 在 v6 和 v5 API 之間提供了一個(gè)兼容性層。 擁有現(xiàn)有應(yīng)用程序的大多數(shù)開發(fā)人員都應(yīng)同時(shí)安裝 來升級(jí) rxjs
和 rxjs-compat
^ 6.0.0 ^ 6.0.0 :
npm install rxjs@6 rxjs-compat@6
有關(guān)此軟件包的詳細(xì)信息,請(qǐng)參見此處 .
兼容性軟件包會(huì)增加應(yīng)用程序的捆綁包大小,這就是為什么我們建議您在應(yīng)用程序和依賴項(xiàng)更新后立即將其刪除。 如果您使用的 Webpack 版本是 4.0.0之前,則此大小增加會(huì)加劇。
有關(guān)要?jiǎng)h除的更新內(nèi)容的完整說明 rxjs-compat
,請(qǐng)參閱下文 刪除兼容性層 。 還要注意,將應(yīng)用程序完全更新到 v6 可能會(huì)暴露以前未顯示的現(xiàn)有類型錯(cuò)誤。
rxjs-compat
,則可能只需要立即解決兩個(gè)重大更改。
同步錯(cuò)誤處理( 放置對(duì) 的調(diào)用 Observable.subscribe()
在 方法 try/catch
不再支持 塊中 )。 如果使用了它,則必須使用 的 將其替換為異步錯(cuò)誤處理 error
回調(diào) Observable.subscribe()
方法中 。
如果要在 TypeScript 中定義自己的原型運(yùn)算符并修改 Observable
名稱空間,則需要更改運(yùn)算符代碼才能編譯 TypeScript。 。 這是一種相對(duì)罕見的情況,可能只影響高級(jí) TypeScript 開發(fā)人員。
取代同步錯(cuò)誤處理 以下示例顯示了在 內(nèi)預(yù)訂可觀察對(duì)象的代碼, try/catch
塊 以便同步處理錯(cuò)誤:
try {
source$.subscribe(nextFn, undefined, completeFn);
} catch (err) {
handleError(err);
}
以下代碼通過定義以下內(nèi)容的錯(cuò)誤回調(diào)將其更新為異步處理錯(cuò)誤 Observable.subscribe()
:
source$.subscribe(nextFn, handleError, completeFn);
下一個(gè)示例顯示了一個(gè)依賴于同步錯(cuò)誤處理的測試:
it('should emit an error on subscription', () => {
expect(source$.subscribe()).toThrow(Error, 'some message');
});
以下代碼顯示了如何更正測試以使用異步錯(cuò)誤處理:
it('should emit an error on subscription', (done) => {
source$.subscribe({
error(err) {
expect(err.message).toEqual('some message');
}
});
});
TypeScript用戶定義的原型運(yùn)算符
以下示例顯示了您需要在用戶定義的原型運(yùn)算符中進(jìn)行的更改類型,以便正確編譯TypeScript。
這是一個(gè)用戶定義的原型運(yùn)算符的示例r:
Observable.prototype.userDefined = function () {
return new Observable((subscriber) => {
this.subscribe({
next(value) { subscriber.next(value); },
error(err) { subscriber.error(err); },
complete() { subscriber.complete(); },
});
});
};
source$.userDefined().subscribe();
要使此代碼在 v6 中正確編譯,請(qǐng)按如下所示進(jìn)行更改:
const userDefined = <T>() => (source: Observable<T>) => new Observable<T>((subscriber) => {
source.subscribe({
next(value) { subscriber.next(value); },
error(err) { subscriber.error(err); },
complete() { subscriber.complete(); },
});
});
});
source$.pipe(
userDefined(),
)
.subscribe();
如果使用從 v6 中刪除但 支持的功能,則 rxjs-compat
軟件包 必須重構(gòu)或重寫代碼以完成對(duì) v6 的更新。 以下功能區(qū)域取決于兼容性層:
如果您是 TypeScript 開發(fā)人員,建議您使用它 rxjs-tslint
來重構(gòu)導(dǎo)入路徑。
對(duì)于 JavaScript 開發(fā)人員,一般規(guī)則如下:
import { Observable, Subject, asapScheduler, pipe, of, from, interval, merge, fromEvent, SubscriptionLike, PartialObserver } from 'rxjs';
import { map, filter, scan } from 'rxjs/operators';
import { webSocket } from 'rxjs/webSocket';
import { ajax } from 'rxjs/ajax';
import { TestScheduler } from 'rxjs/testing';
鏈接運(yùn)算符的以前編碼風(fēng)格已被一個(gè)運(yùn)算符的結(jié)果傳遞給另一個(gè)運(yùn)算符的結(jié)果所取代。 5.5版中添加了可管道運(yùn)算符。
在刪除兼容性層之前,必須重構(gòu)代碼以僅使用可管道運(yùn)算符。 對(duì)于 Typescript,該 tslint
工具通過將轉(zhuǎn)換應(yīng)用于類型正確的代碼來在某種程度上實(shí)現(xiàn)流程自動(dòng)化。
所有可觀察的類,以支持執(zhí)行與類方法相同的操作的現(xiàn)有或新運(yùn)算符。 例如, ArrayObservable.create(myArray)
可以由 替換 from(myArray)
或 為new運(yùn)算符 fromArray()
。
ConnectableObservable
從直接利用隱藏在 V6 和只能通過運(yùn)營商進(jìn)行訪問 multicast
, publish
, publishReplay
,和 publishLast
。 SubscribeOnObservable
在 v6 中無法直接使用,并且只能通過operator進(jìn)行訪問 subscribeOn
。 v6創(chuàng)建功能 | v5類 |
---|---|
from | ArrayLikeObservable |
of | 數(shù)組可觀察 |
bindCallback | BoundCallbackObservable |
bindNodeCallback | BoundNodeCallbackObservable |
defer | 延遲可觀察 |
empty or EMPTY (constant) | 空可觀察 |
throwError | 錯(cuò)誤可觀察 |
forkJoin | 前叉可觀察 |
fromEvent | FromEventObservable |
fromEventPattern | FromEventPatternObservable |
from | FromObservable |
generate | GenerateObservable |
iif | IfObservable |
interval | 間隔可觀察 |
from | IteratorObservable |
NEVER (constant) | 永不觀察 |
pairs | 可觀察對(duì) |
from | 承諾可觀察 |
range | 可觀察范圍 |
of | 標(biāo)量可觀察 |
timer | 計(jì)時(shí)器可觀察 |
using | 使用可觀察 |
結(jié)果選擇器是一個(gè)很少有人使用的功能(在許多情況下沒有記錄),但是卻在代碼庫中增加了很大的膨脹。 如果使用它們,則需要 替換不連續(xù)的 resultSelector
用外部結(jié)果選擇代碼 參數(shù)。
resultSelector
對(duì)參數(shù) first()
和 last()
被 刪除 的 V6 發(fā)動(dòng)機(jī)。 如果使用了這些,則必須將代碼更新為在沒有 情況下運(yùn)行 rxjs-compat
軟件包的 。 resultSelector
已 了許多映射運(yùn)算符可用 參數(shù) 棄用 v6 ,并將實(shí)現(xiàn)重寫為小得多。 它們將在沒有兼容軟件包的情況下繼續(xù)工作,但是必須在 v7 版本之前將其更換。 在 RxJS 發(fā)行 v7 之前,您將需要?jiǎng)h除和替換所有不贊成使用的功能。 以下區(qū)域包含不推薦使用的功能:
Observable.if
和 Observable.throw
這些方法已由 static 代替 iif()
和 throwError()
function 。 使用 rxjs-tslint 將方法調(diào)用與函數(shù)調(diào)用轉(zhuǎn)換。 rxjs/operators
到 rxjs
中,其使用已經(jīng)改變: merge
concat
combineLatest
race
zip
在將點(diǎn)鏈運(yùn)算符轉(zhuǎn)換為可管道運(yùn)算符之前,請(qǐng)確保從中導(dǎo)入所有使用的運(yùn)算符 rxjs/operators
。 例如:
import { map, filter, catchError, mergeMap } from 'rxjs/operators';
更改了以下運(yùn)算符名稱,因?yàn)樗鼈兊狞c(diǎn)鏈名稱是JavaScript中的保留字:
do
-> tap
catch
-> catchError
switch
-> switchAll
finally
-> finalize
要將點(diǎn)鏈運(yùn)算符轉(zhuǎn)換為可管道運(yùn)算符,請(qǐng)將所有運(yùn)算符 包裝在 符 pipe()
從可觀察的源中 方法中,刪除點(diǎn),然后添加逗號(hào)以將每個(gè)運(yùn)算 傳遞 pipe()
作為參數(shù) 。
例如,以下代碼使用鏈接:
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);
轉(zhuǎn)換為管道:
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);
Observable.if> iif()
Observable.if(test, a$, b$);
// becomes
iif(test, a$, b$);
Observable.error> throwError()
Observable.throw(new Error());
// becomes
throwError(new Error());
走
import { merge } from 'rxjs/operators';
a$.pipe(merge(b$, c$));
// becomes
import { merge } from 'rxjs';
merge(a$, b$, c$);
康卡特
import { merge } from 'rxjs/operators';
a$.pipe(merge(b$, c$));
// becomes
import { merge } from 'rxjs';
merge(a$, b$, c$);
結(jié)合最新
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$);
zip
import { zip } from 'rxjs/operators';
a$.pipe(zip(b$, c$));
// becomes
import { zip } from 'rxjs';
zip(a$, b$, c$);
在 RxJS v5.x 中,許多運(yùn)算符都有一個(gè)可選的 resultSelector 參數(shù),您可以在其中傳遞用于處理運(yùn)算結(jié)果的函數(shù)。
如果使用參數(shù),則必須通過將結(jié)果選擇功能移出原始操作員調(diào)用并將其應(yīng)用于調(diào)用結(jié)果的方式來更新代碼。
第一()
source.pipe(
first(predicate, resultSelector, defaultValue)
)
source.pipe(
first(predicate, defaultValue),
map(resultSelector)
)
source.pipe(
map((v, i) => [v, i]),
first(([v, i]) => predicate(v, i)),
map(([v, i]) => resultSelector(v, i)),
)
持續(xù)()
source.pipe(
last(predicate, resultSelector, defaultValue)
)
source.pipe(
last(predicate, defaultValue),
map(resultSelector)
)
source.pipe(
map((v, i) => [v, i]),
last(([v, i]) => predicate(v, i)),
map(([v, i]) => resultSelector(v, i)),
)
mergeMap()
source.pipe(
mergeMap(fn1, fn2, concurrency)
)
source.pipe(
mergeMap((a, i) => fn1(a, i).pipe(
map((b, ii) => fn2(a, b, i, ii))
)),
concurrency
)
mergeMapTo()
source.pipe(
mergeMapTo(a$, resultSelector)
)
source.pipe(
mergeMap((x, i) => a$.pipe(
map((y, ii) => resultSelector(x, y, i, ii))
)
)
concatMap()
source.pipe(
concatMap(fn1, fn2)
)
source.pipe(
concatMap((a, i) => fn1(a, i).pipe(
map((b, ii) => fn2(a, b, i, ii))
)
)
concatMapTo()
source.pipe(
concatMapTo(a$, resultSelector)
)
source.pipe(
concatMap((x, i) => a$.pipe(
map((y, ii) => resultSelector(x, y, i, ii))
)
)
switchMap()
source.pipe(
switchMap((a, i) => fn1(a, i).pipe(
map((b, ii) => fn2(a, b, i, ii))
)
)
source.pipe(
switchMap((a, i) => fn1(a, i).pipe(
map((b, ii) => fn2(a, b, i, ii))
)
)
switchMapTo()
source.pipe(
switchMapTo(a$, resultSelector)
)
source.pipe(
switchMap((x, i) => a$.pipe(
map((y, ii) => resultSelector(x, y, i, ii))
)
)
exhaustMap()
source.pipe(
exhaustMap(fn1, fn2)
)
source.pipe(
exhaustMap((a, i) => fn1(a, i).pipe(
map((b, ii) => fn2(a, b, i, ii))
)
)
forkJoin()
forkJoin(a$, b$, c$, resultSelector)
// or
forkJoin([a$, b$, c$], resultSelector)
forkJoin(a$, b$, c$).pipe(
map(x => resultSelector(...x))
)
// or
forkJoin([a$, b$, c$]).pipe(
map(x => resultSelector(...x))
)
壓縮()
zip(a$, b$, c$, resultSelector)
// or
zip([a$, b$, c$], resultSelector)
zip(a$, b$, c$).pipe(
map(x => resultSelector(...x))
)
// or
zip([a$, b$, c$]).pipe(
map(x => resultSelector(...x))
)
combineLatest()
combineLatest(a$, b$, c$, resultSelector)
// or
combineLatest([a$, b$, c$], resultSelector)
combineLatest(a$, b$, c$).pipe(
map(x => resultSelector(...x))
)
// or
combineLatest([a$, b$, c$]).pipe(
map(x => resultSelector(...x))
)
fromEvent()
fromEvent(button, 'click', resultSelector)
fromEvent(button, 'click').pipe(
map(resultSelector)
)
在 RxJS v6.x 中,UMD 模塊名稱已從Rx更改為 rxjs,以便與其他導(dǎo)入模塊名稱對(duì)齊。
const rx= Rx;
rx.Observable.of(1,2,3).map(x => x + '!!!');
// becomes
const { of } = rxjs;
const { map } = rxjs.operators;
of(1,2,3).pipe(map(x => x + '!!!')); // etc
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: