资讯专栏INFORMATION COLUMN

从命令式到响应式(四)

jaysun / 1349人阅读

摘要:使用的操作符这条从左到右的横线代表经过操作符转换后的输出流。返回值通过判定函数检测的值组成的流。返回值持续发出输入流上的值,直到通知流上发出值为止。

上期介绍过了rxjs中的三大件,Observable,subscription,subject,但是在开发过程我们最常接触到的东西非操作符莫属。比如上期代码中曾出现过的from就是一个操作符。rxjs中的操作符大致上可以分为几类,创建类,组合类,转换类,过滤类,条件类,聚合类,错误处理类,多播类及工具类,其中前四类是数据处理时使用频率非常高的,在本节及下一节中将介绍其中一些使用频率非常高的操作符。rxjs一共提供了120个左右操作符,合理的使用这些操作符会使我们获取愉快的编码体验。

如何学习操作符

首先需要分清的是操作符是属于实例方法还是静态方法,实例方法的实例当然指的是Observable类的实例,通常情况会在数据转换的过程中使用;而静态方法当然指的是Observable类的静态方法,只能通过Observable类来调用,大部分创建类型的操作符都是静态方法,在rxjs5中区别非常明显,例如:

import "rxjs/Observable";
import "rxjs/add/operator/map";

// 这里的interval 是静态方法,而map就是实例方法。
Observable.interval(1000).map(num => num * num);

在rxjs6中还可能这样写:

import { interval } from "rxjs/observable/interval";
import { map } from "rxjs/operators/map";

// 引入的位置是不一样的。
interval(1000)
    .pipe(
        map(num => num * num)
    );

最直观的描述操作符的行为的方式就是弹珠图,在官网上重要的操作符基本上都给出了相应的弹珠图。从现在开始为了表达的简洁,我们把可观测序列称之为流,弹珠图各部分的含义如下:

// 这条从左到右的横线代表随时间的推移,输入流的执行过程。
// 横线上的值代表从流上发射出的值
// 横线尾部的竖线代表complete通知执行的时间点,表示这条流已经成功的执行完成。
----------4------6--------------a-------8-------------|---->

            multipleByTen // 使用的操作符

// 这条从左到右的横线代表经过操作符转换后的输出流。
// 横线尾部的X代表在这个时间点上流发生了错误,至此之后不应该再有 Next 通知或 Complete 通知从流上发出。
---------40-----60--------------X--------------------------->

前面说过操作符会把我们的数据进行转换,在响应式编程中,我们应该尽量保持数据在流中进行转换,而不是时刻想着去subscribe一条流,取出数据,再转换数据。尤其在angular中,能不手动的subscribe的流,一定要力求不主动订阅,最典型的就是页面上需要显示的数据,我们完全可以交给async管道来进行订阅。OK,啰嗦了一大堆,下面主角登场。

创建类操作符

from

静态方法

将数组、类数组对象、promise、部署了遍历器接口的对象或类 Observable 对象转换成Observable,它
几乎可以将任何东西都转换成流,并且将原数据上的值依次推送到流上,字符串被当成由字母组成的数组进行转换。

            from([1,2,3])

    1--------------2--------------3|

示例

from([1,2,3,4,5]).subscribe(v => console.log(v));
function* generatorDoubles(seed) {
    var i = seed;

    while(true) {
        yield i;

        i = i*2
    }
}

const iterator = generatorDoubles(3);
from(iterator).take(5).subscribe(v => console.log(v));

of

静态方法

创建一个流,把传入此函数的参数从左到右依次推送到流上,然后发出结束通知。

            of(1,2,3);

    1-------------2--------------3|

示例

of(10,20,30).subscribe(v => console.log(v));

timer

静态方法

创建一个输出流,在指定的延迟时间到达后开始发射值,在指定的间隔时间到达后发射递增过的值。类似于interval,但是这个操作符允许指定流开始发射值的时间,

            timer(3000, 1000);

    ------0--1--2--3--4--5--------->

第一个参数代表等待时间,第二个参数代表时间间隔,这些值是一些数字常量。等待时间可以是一个毫秒数,也可以是一个日期对象。如果没有指定时间周期,输出流上只会发射0,反之,它会发出一个无限的数列。

示例

Rx.Observable.timer(3000, 1000)
    .subscribe(v => console.log(v));
Rx.Observable.timer(5000)
    .subscribe(v => console.log(v));
过滤类操作符

filter

实例方法

创建一个流,它的值是使用判定函数对输入流发出的值进行过滤后的值。

    --0--1--2--3--4--5----|-->

            filter(v => v % 2 === 0);

    --0-----2-----4-------|>

和数组的filter方法行为一样,从输入流上获取值,使用判定函数对值进行过滤,只有符合过滤条件的值才会在输出流上发出。

返回值 Observable 通过判定函数检测的值组成的流。

示例

from([1,2,3,4,5,6])
    .filter(num => num %2 === 0)
    .subscribe(v => console.log(v));

first

实例方法

发送输入流上的第一个值,或者第一个符合某些条件的值。

    ---------a-------b------c---------d-->

            first

    ---------a|

在不传入任何参数时,这个操作符仅发出输入流上的第一个值,然后立即发出结束通知。如果传入一个判定函数,则发出第一个通过判定函数检测的值。它还可以接受一个结果控制函数来转化输出的值,或一个在输入流没有发出符合条件的值情况下使用的默认值。如果没有提供默认值,并且在输入流上也没有找到符合条件的值时,输出流将会抛出错误。

返回值 Observable 第一个符合条件的值。

异常 EmptyError 在结束通知发出前如果没有发出过有效值,将会发送一个错误通知给观察者。

示例

from([2,3,4])
    .first()
    .subscribe(v => console.log(v));
from([2,3,4])
    .first(num => num === 5)
    .subscribe(v => console.log(v)); // EmptyError;

skip

实例方法

返回一个跳过指定数量的值的流。

---a---b---c---d---e---|->

            skip(3);

---------------d---e---|>

返回值 Observable 跳过了一定数量值的流。

示例

from([1,2,3,4,5,6])
    .skip(3)
    .subscribe(v => console.log(v));

take

实例方法

从第一个值开始发出指定数量的值,然后发出结束通知。

    ---a------b------c------d-----e---|-->

            take(3);

    ---a------b------c|

输出流仅仅发出了输入流上从第一个值开始的n个值。如果输入流上值的个数小于n,那么所有的值都会被发出。值发射完成后,不管输入流有没有发出结束通知,输出流都会立即发出结束通知。

返回值 Observable 发出输入流上从第一个值开始的n个值,或者输入流发出值的个数小于n时发出所有的值的流。

异常 ArgumentOutOfRangeError 在给此操作符传入负数时给观察者发出的错误。

示例

interval(1000)
    .take(5)
    .subscribe(v => console.log(v));

takeUntil

实例方法

在通知流发出通知之前,持续发射输入流上的值。在通知流发出值之前,输出流完全就是输入流的镜像。此操作符会一直监视传入的通知流,如果通知流发出了值或结束通知,输出流就会停止发射输入流上的值,并发出完成通知。

返回值 Observable 持续发出输入流上的值,直到通知流上发出值为止。

示例

Rx.Observable.interval(1000)
    .takeUntil(Rx.Observable.fromEvent(document, "click"))
    .subscribe(v => console.log(v));

学习操作符时,我们还要关注的一点是,这个操作符是否会发出结束通知,一方面订阅发出结束通知的流时,在库的底层会帮助我们释放资源可以省去手动取消订阅,比如 angular 中 http 服务上的方法,另一方面结束通知可能会影响接下来你使用的操作符,典型的如reduce 和 scan,在一个不发出结束通知的流上使用reduce时你将永远不会得到结果。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/97262.html

相关文章

  • 命令响应(一)

    摘要:响应式命令式这两种编程风格的思维方式是完全相反的。第二种方式是工人主动去找工人索取生产手机所要的零件,然后生产一台完整的手机,这两种方式就对应的响应式和命令式。 angular2中内置了rxjs,虽然框架本身并没有强制开发者使用响应式风格来组织代码,但是从框架开发团队的角度可以看出他们必然是认同这种编程风格的。rxjs本质是基于函数式编程的响应式风格的库,函数式相对于面向对象来说更加抽...

    JayChen 评论0 收藏0
  • 前端入门24-响应布局(BootStrap)

    摘要:声明声明本篇内容摘抄自以下两个来源中文网感谢大佬们的分享。版本是全球最受欢迎的前端组件库,用于开发响应式布局移动设备优先的项目。官方示例官方示例版本,官方还没有中文教程,的中文教程倒是很齐全了。声明 本篇内容摘抄自以下两个来源: BootStrap中文网 感谢大佬们的分享。 正文-响应式布局(BootStrap) 这次想来讲讲一个前端开发框架:BootStrap BootStrap 目前...

    lunaticf 评论0 收藏0
  • 足机器狗——12自由度舵机狗DIY(一)

    摘要:四足仿生机器人具有高机动性,负载能力和适应能力强,可运用于物资运输抢险救援等方面,具有广阔前景。由于制作电机狗需要高昂的成本。自主设计制造一款舵机狗来学习研究四足机器狗的步态算法是一件性价比极高且很有意义的一件事。 文章目录 前言 一、初步了解四足结构 1.1.2串联机构 1.2 ...

    不知名网友 评论0 收藏0
  • 命令响应(六)

    摘要:从这个系列的第一章开始到第五章,基于的响应式编程的基础知识基本上就介绍完了,当然有很多知识点没有提到,比如,等,不是他们不重要,而是碍于时间精力等原因没办法一一详细介绍。 从这个系列的第一章开始到第五章,基于rxjs的响应式编程的基础知识基本上就介绍完了,当然有很多知识点没有提到,比如 Scheduler, behaviorSubject,replaySubject等,不是他们不重要,...

    sanyang 评论0 收藏0
  • vue源码分析系列之响应数据(

    摘要:执行当时传入的回调,并将新值与旧值一并传入。文章链接源码分析系列源码分析系列之环境搭建源码分析系列之入口文件分析源码分析系列之响应式数据一源码分析系列之响应式数据二源码分析系列之响应式数据三 前言 上一节着重讲述了initComputed中的代码,以及数据是如何从computed中到视图层的,以及data修改后如何作用于computed。这一节主要记录initWatcher中的内容。 ...

    GHOST_349178 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<