Pipeable Operators
从版本5.5开始,我们发布了”pipe operators”,可以直接在rxjs/operators
访问操作符。 与rxjs/ add/operator/*
中的操作符相比,这仅仅是一种更好的方法来引入所需的操作符。
注意:通过rxjs/operators
引入的操作符,如果你的构建程序不更改配置的话,最后打包的文件会变大,不过没关系,Known Issues部分会给出解决办法。
改名的操作符
由于操作符可独立于Observable对象使用,操作符不能与JavaScript关键字冲突。 因此对某些操作符的可移植版本的名称进行更改。 有以下操作符:
do
->tap
catch
->catchError
switch
->switchAll
finally
->finalize
let
操作符现在是Observable
的一部分,并且不能被导入。source$.let(myOperator) -> source$.pipe(myOperator)
现在移除了toPromise()
操作符,因为它返回的是Observable
而并不是Promise
。现在使用Observable.toPromise()
实例方法。
因为throw
是关键字,用_throw
来导入。import { _throw } from 'rxjs/observable/throw'
如果_
这个符号很困扰你,可以使用以下方法:1
2
3
4import { ErrorObservable } from 'rxjs/observable/ErrorObservable';
...
const e = ErrorObservable.create(new Error('My bad'));
const e2 = new ErrorObservable(new Error('My bad too'));
Why?
patched
操作符链式调用的问题:
任何导入
patched
操作符的库都会为该库的所有使用者增加Observable.prototype
,从而创建盲目的依赖关系。 如果删除这类库,这可能会不知不觉地影响其他人的引用。 使用pipeables
,你必须将你需要的操作符导入到正在使用它们的每个文件中。直接添加到原型上的操作符不会像
rollup
或webpack
这样的工具“进行摇树优化”。pipeable
操作符将会像它们直接从模块中引入的功能一样。无法通过任何构建工具或
lint rule
可靠地检测到正在应用中导入但并未使用的操作符。 这意味着你可能会导入scan
,但不再使用它,它仍然被添加到你的输出包中。 对于pipeable
操作符,如果你不使用它,lint rule
可以为你检测出来。这种设计很棒。 构建自己的自定义操作符变得非常容易,现在它们的工作方式与rxjs中的所有其他操作符一样。 你不需要扩展
Observable
或重写lift
。
What?
什么是pipeable
操作符? 简而言之,可以与当前let
运算符一起使用的函数。 它曾经是名称的起源(“lettable”),但是这让人觉得很奇怪,所以改为“pipeable”,因为它们打算与pipe
功能一起使用。 一个pipeable
操作符基本上是任何返回一个带有签名函数的函数:<T,R>(source:Observable <T>)=> Observable <R>
。
现在在Observable.prototype.pipe
中有一个’Observable内置的
pipe`方法,它类似于以前的链式组合操作符。(如下所示)
在rxjs / util / pipe
上还有pipe
实用功能,可用于从其他pipeable
操作符构建可重复使用的pipeable
操作符。
Usage
你可以在rxjs / operators
(复数)下导入所需的操作符。 还推荐直接使用Observable创建方法,如下所示,使用`range’:
1 | import { range } from 'rxjs/observable/range'; |
Build Your Own Operators Easily
实际上,你可以用let
来做到这一点……但是构建你自己的操作符就像现在写一个函数一样简单。 请注意,可以无缝地与其他rxjs操作符组成自定义操作符。
1 | import { interval } from 'rxjs/observable/interval'; |
Known Issues
TypeScript < 2.4
在TypeScript 2.3及更低版本中,需要将类型添加到传递给操作符的函数中,因为类型不能在TypeScript 2.4之前推断出来。 在TypeScript 2.4中,类型将通过合成来正确推断。
TS 2.3及以下
1 | range(0, 10).pipe( |
TS 2.4及以上
1 | range(0, 10).pipe( |
Build and Treeshaking
从main
(或重新导出)文件导入时,应用程序包有时可能会增长。 现在从rxjs / operators
中导入可管理的操作符,但是如果不更改构建过程,通常会导致更大的应用程序包。 这是因为默认rxjs / operators
会解析为rxjs的CommonJS输出。
为了使用新的pipeable
操作符而不增加打包的体积,需要更改Webpack配置。 这种方法只适用于Webpack 3+,因为它依赖于来自Webpack 3新的特性ModuleConcatenationPlugin
。
path-mapping
与rxjs 5.5一起发布的版本是使用ES5和ES2015语言级别的ECMAScript模块格式(导入和导出)的rxjs版本。 你可以在node_modules/rxjs/_esm5
和node_modules/rxjs/_esm2015
(“esm”代表ECMAScript模块,数字“5”或“2015”代表ES语言级别)中找到这些分布。 在你的代码中,应该从rxjs / operators
中导入,但在Webpack配置文件中,需要将导入重新映射到ESM5(或ESM2015)版本。
如果你需要使用(’rxjs / _esm5 / path-mapping’)`,将收到一个函数,该函数返回一个键值对的对象,将每个输入映射到磁盘上的文件位置。 如下:
webpack.config.js
1 | const rxPaths = require('rxjs/_esm5/path-mapping'); |
or
1 | const webpack = require('webpack'); |
无法控制构建过程时
如果无法控制构建过程(或者无法升级到Webpack 3+),则上述解决方案将无法工作。 因此,从rxjs / operators
导入可能会使你的应用程序包变大。 但是,仍然有一种方法可以使用pipeable
操作符。 你必须使用深导入,这与你在5.5版之前导入的方式和pipeable
操作符相似:
1 | import { map, filter, reduce } from 'rxjs/operators'; |