RxJS 中的管道有什么用?
What is pipe for in RxJS?
我想我已经有了基本的概念,但还有一些晦涩难懂的地方
所以通常这就是我使用 Observable
:
的方式
observable.subscribe(x => {
})
如果我想过滤数据,我可以使用这个:
import { first, last, map, reduce, find, skipWhile } from 'rxjs/operators';
observable.pipe(
map(x => {return x}),
first()
).subscribe(x => {
})
我也可以这样做:
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
observable.map(x => {return x}).first().subscribe(x => {
})
所以我的问题是:
- 有什么区别?
- 如果没有区别,为什么函数
pipe
存在?
- 为什么这些函数需要不同的导入?
“pipeable”(以前的“lettable”)运算符是自 RxJS 5.5 以来使用运算符的当前和推荐方式。
我强烈建议您阅读 official documentation on pipeable operators
主要区别在于,创建自定义运算符更容易,并且在不更改某些全局 Observable
对象的情况下更好地进行 treeshaking,如果两个不同的方想要创建同名运算符,则可能会发生冲突.
为每个运算符 'rxjs/add/operator/first'
使用单独的 import
语句是一种制作更小的应用程序包的方法。通过仅导入您需要的运算符而不是整个 RxJS 库,您可以显着减少总包大小。但是,编译器无法知道您是否导入了 'rxjs/add/operator/first'
,因为您在代码中确实需要它,或者您只是在重构代码时忘记删除它。这是使用管道运算符的优势之一,其中未使用的导入会自动被忽略。
管道法
According to original Documentation
pipable 运算符是 函数将 observables 作为输入,它 returns 另一个 observable.previous observable 保持不变。
pipe(...fns: UnaryFunction<any, any>[]): UnaryFunction<any, any>
What pipe mean?
That means that any operators you previously used on the instance of
observable are available as pure functions under rxjs/operators
.
This makes building a composition of operators or re-using operators
becomes really easy, without having to resort to all sorts of
programming gymnastics where you have to create a custom observable
extending Observable, then overwrite lift just to make your own custom
thing.
const { Observable } = require('rxjs/Rx')
const { filter, map, reduce, } = require('rxjs/operators')
const { pipe } = require('rxjs/Rx')
const filterOutWithEvens = filter(x => x % 2)
const doubleByValue = x => map(value => value * x);
const sumValue = reduce((acc, next) => acc + next, 0);
const source$ = Observable.range(0, 10)
source$.pipe(
filterOutWithEvens,
doubleByValue(2),
sumValue)
.subscribe(console.log); // 50
我得出的一个很好的总结是:
它将流操作(map、filter、reduce...)与核心功能(订阅、管道)分离。通过管道操作而不是链接,它不会污染 Observable 的原型,从而更容易进行 tree shaking。
见https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#why
Problems with the patched operators for dot-chaining are:
Any library that imports a patch operator will augment the
Observable.prototype for all consumers of that library, creating blind
dependencies. If the library removes their usage, they unknowingly
break everyone else. With pipeables, you have to import the operators
you need into each file you use them in.
Operators patched directly onto the prototype are not "tree-shakeable"
by tools like rollup or webpack. Pipeable operators will be as they
are just functions pulled in from modules directly.
Unused operators that are being imported in apps cannot be detected
reliably by any sort of build tooling or lint rule. That means that
you might import scan, but stop using it, and it's still being added
to your output bundle. With pipeable operators, if you're not using
it, a lint rule can pick it up for you.
Functional composition is awesome. Building your own custom operators
becomes much, much easier, and now they work and look just like all
other operators from rxjs. You don't need to extend Observable or
override lift anymore.
有什么区别?
正如您在示例中看到的,主要区别在于提高了源代码的可读性。您的示例中只有两个函数,但想象一下如果有十几个函数?然后它会像
function1().function2().function3().function4()
它真的变得很难看,而且难以阅读,尤其是当你在函数内部填充时。最重要的是某些编辑器,如 Visual Studio 代码不允许超过 140 行长度。但如果它像下面这样。
Observable.pipe(
function1(),
function2(),
function3(),
function4()
)
这大大提高了可读性。
如果没有区别,为什么会有管道功能?
PIPE() 函数的目的是 将所有采用的函数集中在一起 ,并且 return 可观察。它最初采用一个可观察对象,然后该可观察对象在整个 pipe() 函数中被其中使用的每个函数使用。
第一个函数获取observable,处理它,修改它的值,然后传递给下一个函数,然后下一个函数获取第一个函数的输出observable,处理它,传递给下一个函数,然后它去直到 pipe() 函数内的所有函数都使用该可观察对象,最后您得到了已处理的可观察对象。最后,您可以使用 subscribe() 函数执行可观察对象以从中提取值。请记住,原始 observable 中的值没有改变。!!
为什么这些函数需要不同的导入?
导入取决于函数在 rxjs 包中指定的位置。
它是这样的。所有模块都存储在 Angular 中的 node_modules 文件夹中。
从 "module" 导入 { class };
我们以下面的代码为例。我刚刚在 stackblitz 中写了它。因此,不会自动生成任何内容,也不会从其他地方复制任何内容。当您也可以去阅读 rxjs 文档时,我看不出复制 rxjs 文档中的内容有什么意义。我假设您在这里问了这个问题,因为您不了解文档。
- 有 pipe, observable, of, map class 从
各自的模块。
- 在 class 的正文中,我使用了 Pipe() 函数
如代码中所示。
Of() 函数 return 是一个可观察的,即
订阅时按顺序发出数字。
Observable 尚未订阅。
当您像 Observable.pipe() 这样使用它时,pipe() 函数使用给定的 Observable 作为输入。
第一个函数,map()函数使用那个Observable,处理它,return处理过的Observable返回给pipe()函数,
然后处理过的Observable如果有的话就交给下一个函数,
一直这样下去,直到所有函数都处理 Observable,
最后 Observable 被 pipe() 函数 returned 到一个变量,在下面的例子中是它的 obs。
现在 Observable 的问题是,只要观察者没有订阅它,它就不会发出任何值。所以我用subscribe()函数订阅了这个Observable,然后一订阅就订阅。 of() 函数开始发射值,然后通过 pipe() 函数处理它们,最后得到最终结果,例如 1 从 of() 函数中取出,1 在 map() 函数中添加 1,然后 return 回来了。您可以在 subscribe( function (argument) {} ) 函数中将该值作为参数获取。
如果要打印,则用作
subscribe( function (argument) {
console.log(argument)
}
)
import { Component, OnInit } from '@angular/core';
import { pipe } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
obs = of(1,2,3).pipe(
map(x => x + 1),
);
constructor() { }
ngOnInit(){
this.obs.subscribe(value => console.log(value))
}
}
我是这样解释 observable 的:
您需要根据天气状况制定计划,因此您打开收音机并收听全天候 24/7 广播天气状况的天气频道。在这种情况下,响应是持续的,而不是得到一个单一的响应。此响应类似于对可观察对象的订阅。可观察的是“天气”,订阅是“让您了解最新情况的无线电信号”。只要您的收音机开着,您就会获得所有可用的更新。在您关闭收音机之前,您不会错过任何信息。
我说天气是可以观察到的,但你是在听收音机而不是天气。所以收音机也是可观察的。天气播音员说的是气象学家发给他的天气预报的功能。气象学家写的是来自气象站的数据的函数。来自气象站的数据是与其相连的所有仪器(气压计、风衰减器、风量计)的函数,而这些仪器是天气本身的函数。
整个过程中至少有 5 个 observable。在这个过程中,有两种类型的可观察量。源可观察和输出可观察。在这个例子中,天气是“源可观察”,收音机是“输出可观察”。中间的所有内容代表 PIPE FUNCTION
.
管道函数 是让源可观察对象对其执行操作以提供输出可观察对象,所有这些操作都在内部发生。这些操作都处理 observables 本身
我想我已经有了基本的概念,但还有一些晦涩难懂的地方
所以通常这就是我使用 Observable
:
observable.subscribe(x => {
})
如果我想过滤数据,我可以使用这个:
import { first, last, map, reduce, find, skipWhile } from 'rxjs/operators';
observable.pipe(
map(x => {return x}),
first()
).subscribe(x => {
})
我也可以这样做:
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
observable.map(x => {return x}).first().subscribe(x => {
})
所以我的问题是:
- 有什么区别?
- 如果没有区别,为什么函数
pipe
存在? - 为什么这些函数需要不同的导入?
“pipeable”(以前的“lettable”)运算符是自 RxJS 5.5 以来使用运算符的当前和推荐方式。
我强烈建议您阅读 official documentation on pipeable operators
主要区别在于,创建自定义运算符更容易,并且在不更改某些全局 Observable
对象的情况下更好地进行 treeshaking,如果两个不同的方想要创建同名运算符,则可能会发生冲突.
为每个运算符 'rxjs/add/operator/first'
使用单独的 import
语句是一种制作更小的应用程序包的方法。通过仅导入您需要的运算符而不是整个 RxJS 库,您可以显着减少总包大小。但是,编译器无法知道您是否导入了 'rxjs/add/operator/first'
,因为您在代码中确实需要它,或者您只是在重构代码时忘记删除它。这是使用管道运算符的优势之一,其中未使用的导入会自动被忽略。
管道法
According to original Documentation
pipable 运算符是 函数将 observables 作为输入,它 returns 另一个 observable.previous observable 保持不变。
pipe(...fns: UnaryFunction<any, any>[]): UnaryFunction<any, any>
What pipe mean?
That means that any operators you previously used on the instance of observable are available as pure functions under
rxjs/operators
. This makes building a composition of operators or re-using operators becomes really easy, without having to resort to all sorts of programming gymnastics where you have to create a custom observable extending Observable, then overwrite lift just to make your own custom thing.
const { Observable } = require('rxjs/Rx')
const { filter, map, reduce, } = require('rxjs/operators')
const { pipe } = require('rxjs/Rx')
const filterOutWithEvens = filter(x => x % 2)
const doubleByValue = x => map(value => value * x);
const sumValue = reduce((acc, next) => acc + next, 0);
const source$ = Observable.range(0, 10)
source$.pipe(
filterOutWithEvens,
doubleByValue(2),
sumValue)
.subscribe(console.log); // 50
我得出的一个很好的总结是:
它将流操作(map、filter、reduce...)与核心功能(订阅、管道)分离。通过管道操作而不是链接,它不会污染 Observable 的原型,从而更容易进行 tree shaking。
见https://github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md#why
Problems with the patched operators for dot-chaining are:
Any library that imports a patch operator will augment the Observable.prototype for all consumers of that library, creating blind dependencies. If the library removes their usage, they unknowingly break everyone else. With pipeables, you have to import the operators you need into each file you use them in.
Operators patched directly onto the prototype are not "tree-shakeable" by tools like rollup or webpack. Pipeable operators will be as they are just functions pulled in from modules directly.
Unused operators that are being imported in apps cannot be detected reliably by any sort of build tooling or lint rule. That means that you might import scan, but stop using it, and it's still being added to your output bundle. With pipeable operators, if you're not using it, a lint rule can pick it up for you.
Functional composition is awesome. Building your own custom operators becomes much, much easier, and now they work and look just like all other operators from rxjs. You don't need to extend Observable or override lift anymore.
有什么区别? 正如您在示例中看到的,主要区别在于提高了源代码的可读性。您的示例中只有两个函数,但想象一下如果有十几个函数?然后它会像
function1().function2().function3().function4()
它真的变得很难看,而且难以阅读,尤其是当你在函数内部填充时。最重要的是某些编辑器,如 Visual Studio 代码不允许超过 140 行长度。但如果它像下面这样。
Observable.pipe(
function1(),
function2(),
function3(),
function4()
)
这大大提高了可读性。
如果没有区别,为什么会有管道功能? PIPE() 函数的目的是 将所有采用的函数集中在一起 ,并且 return 可观察。它最初采用一个可观察对象,然后该可观察对象在整个 pipe() 函数中被其中使用的每个函数使用。
第一个函数获取observable,处理它,修改它的值,然后传递给下一个函数,然后下一个函数获取第一个函数的输出observable,处理它,传递给下一个函数,然后它去直到 pipe() 函数内的所有函数都使用该可观察对象,最后您得到了已处理的可观察对象。最后,您可以使用 subscribe() 函数执行可观察对象以从中提取值。请记住,原始 observable 中的值没有改变。!!
为什么这些函数需要不同的导入? 导入取决于函数在 rxjs 包中指定的位置。 它是这样的。所有模块都存储在 Angular 中的 node_modules 文件夹中。 从 "module" 导入 { class };
我们以下面的代码为例。我刚刚在 stackblitz 中写了它。因此,不会自动生成任何内容,也不会从其他地方复制任何内容。当您也可以去阅读 rxjs 文档时,我看不出复制 rxjs 文档中的内容有什么意义。我假设您在这里问了这个问题,因为您不了解文档。
- 有 pipe, observable, of, map class 从 各自的模块。
- 在 class 的正文中,我使用了 Pipe() 函数 如代码中所示。
Of() 函数 return 是一个可观察的,即 订阅时按顺序发出数字。
Observable 尚未订阅。
当您像 Observable.pipe() 这样使用它时,pipe() 函数使用给定的 Observable 作为输入。
第一个函数,map()函数使用那个Observable,处理它,return处理过的Observable返回给pipe()函数,
然后处理过的Observable如果有的话就交给下一个函数,
一直这样下去,直到所有函数都处理 Observable,
最后 Observable 被 pipe() 函数 returned 到一个变量,在下面的例子中是它的 obs。
现在 Observable 的问题是,只要观察者没有订阅它,它就不会发出任何值。所以我用subscribe()函数订阅了这个Observable,然后一订阅就订阅。 of() 函数开始发射值,然后通过 pipe() 函数处理它们,最后得到最终结果,例如 1 从 of() 函数中取出,1 在 map() 函数中添加 1,然后 return 回来了。您可以在 subscribe( function (argument) {} ) 函数中将该值作为参数获取。
如果要打印,则用作
subscribe( function (argument) {
console.log(argument)
}
)
import { Component, OnInit } from '@angular/core';
import { pipe } from 'rxjs';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
obs = of(1,2,3).pipe(
map(x => x + 1),
);
constructor() { }
ngOnInit(){
this.obs.subscribe(value => console.log(value))
}
}
我是这样解释 observable 的:
您需要根据天气状况制定计划,因此您打开收音机并收听全天候 24/7 广播天气状况的天气频道。在这种情况下,响应是持续的,而不是得到一个单一的响应。此响应类似于对可观察对象的订阅。可观察的是“天气”,订阅是“让您了解最新情况的无线电信号”。只要您的收音机开着,您就会获得所有可用的更新。在您关闭收音机之前,您不会错过任何信息。
我说天气是可以观察到的,但你是在听收音机而不是天气。所以收音机也是可观察的。天气播音员说的是气象学家发给他的天气预报的功能。气象学家写的是来自气象站的数据的函数。来自气象站的数据是与其相连的所有仪器(气压计、风衰减器、风量计)的函数,而这些仪器是天气本身的函数。
整个过程中至少有 5 个 observable。在这个过程中,有两种类型的可观察量。源可观察和输出可观察。在这个例子中,天气是“源可观察”,收音机是“输出可观察”。中间的所有内容代表 PIPE FUNCTION
.
管道函数 是让源可观察对象对其执行操作以提供输出可观察对象,所有这些操作都在内部发生。这些操作都处理 observables 本身