介绍:

在RxJS的世界中,一切都以数据流为中心,在代码中,数据流以Observable类的实例对象形式存在,创建Observable对象就是数据流处理的开始。

所谓创建类操作符,就是在不依赖于其他Observable对象,可以凭空或者根据其他数据源能够创造出一个Observable对象的方法。创建类操作符并不是不需要任何输入,大多数创建型的操作符都接受输入参数,有的还需要其他的数据源,比如浏览器的DOM结构或者WebSocket。重要的是,创建类操作符往往不会从其他Observable对象获取数据源,在数据管道中,创建类操作符是RxJS中数据流的源头,只有获得数据流之后,才可以发挥RxJS其他操作符的强大功能。

对于创建数据流应该明确区分同步数据流和异步数据流的创建。对于同步数据流,关心的只是产生什么样的数据,已经产生数据的顺序关系,数据之间没有时间间隔,所以不需要考虑异步的情况。对于异步数据流,除了要考虑产生什么样的数据,还要考虑产生数据之间的间隔,也就是产生数据的节奏。

因创建类操作的特性,创建类操作符大部分都是静态操作符。

在日常工作中,我们应该尽量使用创建类操作符,避免直接利用Observable的构造函数来创造Observable对象,RxJS提供的创建类操作符覆盖了几乎所有的数据流创建模式,没有必要重复造轮子。

下面的代码均是以rxjs6版本写的。

同步数据流:

1. create:不需要导入任何其他模板就可以直接使用。

import { Observable } from 'rxjs';
Observable.create = function(subscribe){ return new Observable(subscribe)}

create这个操作符并没有给我们带来任何神奇的功能,使用它和直接使用Observable构造函数没什么区别,所以,绝大部分情况用不上它。

2. of: 列举数据

import { of } from 'rxjs';
const source$ = of(1,2,3)
source$.subscribe(console.log,null,() => console.log('complete')
)

of产生的是Cold Observable,对于每一个Observer都会重复吐出同样的一组数据,所以可以反复使用。

在现实项目中,适合使用of的场景是已知不多的几个数据,需要把这些数据用Observable对象来封装,而且也不需要这些数据的处理要有时间间隔。

3. range: 指定范围

import { range } from 'rxjs';
const source$ = range(1,100);

range第一个参数是数字序列开始的数字,第二个参数是数字序列的长度。从初始化开始,每次递增1,初始化数字可以是整数,也可以是小数。

和of一样,range以同步的方式吐出数据。

三个极简的操作符:empty、never 和 throw

empty、never 和 throw是比较有意思的三个操作符,它们产生的Observable对象十分简单,简单得看起来似乎没有什么价值,不过,当需要默认立刻完结、立刻出错或者永不完结的数据流对象时,这三个操作符可以直接使用。

4. empty:产生一个直接完结的Observable对象,没有参数,不产生任何数据,直接完结。

import { EMPTY} from 'rxjs';
const source$ = EMPTY

5. never: 创建一个不向观察者发出任何项的 Observable。产生的Observable对象什么动作都没有,既不吐数据,也不完结,也不产生错误。

import { NEVER } from 'rxjs';
function info() {console.log('Will not be called');
}
// 发出7, 然后不发出任何值(也不发出完成通知)
const result = NEVER().startWith(7);
result.subscribe(x => console.log(x), info, info);

6. throw: 创建一个不发送数据给观察者并且立马发出错误通知的 Observable。产生的Observable对象什么都不做,直接出错,抛出的错误就是throw的参数。

import { throw } from 'rxjs';
// 先发出数字7,然后发出错误通知
const result = throw(new Error('oops!')).startWith(7);
result.subscribe(x => console.log(x), e => console.error(e));

这三个操作符通常用在Observable对象的最后一步。

异步数据流:

1. interval和timer:定时产生数据

在JavaScript中要模拟异步的处理,通常就是用JavaScript自带的两个函数setInterval和setTimeout,通过指定时间,让一些指令在一段时间之后再执行。可以说,在RxJS中,interval和timer这两个操作符的地位就等同于原生JavaScript的setInterval和setTimeout。地位等同,但功能并不完全一样。

import { interval } from 'rxjs';
const source1$ = interval(1000)

上面该代码在1秒钟的时刻吐出数据0,在2秒钟的时刻吐出数据1,在3秒钟的时刻吐出数据2……。该数据流不会完结,因为interval不会主动调用下游的complete,要想停止这个数据流,必须调用退订的操作。

interval产生的异步数据流总是从0开始递增,如需要从1开始递增,代码如下:

import { interval } from 'rxjs';
import { map } from 'rxjs/operators'
const source$ = Observable.interval(1000)
const result$ = source$.map(x=> x + 1)

要解决复杂的问题,应该用多个操作符的组合,而不是让一个操作符的功能无限膨胀。

由上面的描述可知,interval就是RxJS世界中的setInterval,区别只是setInterval定时调用一个函数,而interval返回的是Observable对象定时产生的一个数据。

timer是RxJS世界中的setTimeout。timer的第一个参数可以是一个数值,也可以是一个Date类型的对象。

第一个参数是数值,代表毫秒数,产生的Observable对象在指定毫秒之后会吐出一个数据0,然后立刻完结,代码如下:

import { timer } from 'rxjs';
const source$ = timer(1000)

通过传递一个Date对象给timer来实现,代码如下:

import { timer } from 'rxjs';
const now = new Date()
const later = new Date(now.getTime() + 1000)
const source$ = timer(later)

使用时间参数还是Date对象作为参数,应该根据具体情况而定,如果明确延时产生数据的时间间隔,那就应该用数值作为参数,如果明确一个时间点点,那就用Date对象作为参数是最佳选择。

timer还支持第二个参数,如果使用第二个参数,那就会产生一个持续吐出数据的Observable对象,类似interval的数据流。第二个参数指定的是各数据之间的时间间隔,从被订阅到产生第一个数据0的时间间隔,依然由第一个参数决定。

import { timer } from 'rxjs';
const source$ = timer(2000,1000)

上面的该代码在source$被订阅之后,在2秒钟的时刻吐出0,然后在3秒钟的时刻吐出1,在4秒钟的时刻吐出2……,永不完结的流。

timer支持产生持续的数据序列,这和setTimeout就不一样,setTimeout只能支持一次异步操作,从这个角度看,timer的功能就是setTimeout的超集

如果timer的第一个参数和第二个参数一样,那就和interval的功能完全一样了,代码如下:

import { interval, timer } from 'rxjs';
const source1$ = interval(1000)
const source2$ = timer(1000, 1000)

2. from:可把一切转化为Observable

from可能是创建类操作符中包容性最强的一个,因为它接受的参数只要“像”Observable就行,然后根据参数中的数据产生一个真正的Observable对象。

“像”Observable的对象很多,一个数组就像Observable,一个不是数组但是“像”数组的对象也算,一个字符串也很像Observable,一个JavaScript中的generator也很像Observable,一个Promise对象也很像,所以from可以把任何对象都转化为Observable对象。

import { from, of } from 'rxjs';
const source$ = from([1,2,3])const another$ = of(1,2,3)
const source1$ = from(another$)

在上面的代码中,source$的数据流与another$完全一样,既然我们有了another$这个Observable,为什么还要转化为source$呢。

from还可以接受Promise对象,行为和fromPromise完全一样。

3. fromPromise:异步处理的交接

如果from的参数是Promise对象,那么这个Promise成功结束,from产生的Observable对象就会吐出Promise成功的结果,并且立刻结束。当Promise对象以失败而告终,from产生的Observable对象也会立刻产生失败事件。

import { from } from 'rxjs';
const promiseResolve = Promise.resolve('good')
const resolveSource$ = from(promiseResolve)
resolveSource$.subscribe(console.log,error => console.log('catch',error),() => console.log('complete')
)
// 运行结果
good
completeconst promiseReject = Promise.reject('bad')
const rejectSource$ = from(promiseReject)
rejectSource$.subscribe(console.log,error => console.log('catch',error),() => console.log('complete')
)
// 运行结果
catch bad

4. fromEvent: 获取用户在网页中的操作事件,把DOM中的事件转化为Observable对象中的数据,产生的是Hot Observable。

fromEvent的第一个参数是一个事件源,在浏览器中,最常见的事件源就是特定的DOM元素,第二个参数是事件的名称,对应DOM事件就是click,mousemove,resize, scroll等。

在网页应用中的用法,代码如下:

<div><button id="clickMe">Click Me</button><div id="text">0</div>
</div>// RxJS 实现
import { fromEvent } from 'rxjs';
let clickCount = 0;
const event$ = fromEvent(document.querySelector('click'))
event$.subscrive(() => {document.querySelector('#text').innerText = ++clickCount;    }
)

另一种应用,如给网页背景增加水印,获取网页的大小,代码如下:

import { fromEvent } from 'rxjs';
const resize$ = fromEvent(window, 'resize')
const scroll$ = fromEvent(window, 'scroll')
// 通过merge操作符继续逻辑处理
merge(resize$, scroll$).pipe();

fromEvent是DOM和RxJS世界的桥梁,产生Observable对象之后,就可以完全按照RxJS的规则来处理数据。除了可以从DOM中获取数据,还可以从Node.js的events中获取数据,代码如下:

import { fromEvent } from 'rxjs';
import EventEmitter from 'events';
const emitter = new EventEmitter()
const source$ = fromEvent(emitter, 'msg')
source$.subscribe(console.log,error => console.log('catch',error),() => console.log('complete')
)
emitter.emit('msg', 1)
emitter.emit('msg', 2)
emitter.emit('msgs', 'bad')
emitter.emit('msg', 3)
// 运行结果
1
2
3

在上面的代码中,emitter发送的事件名称为msg,事件对象是数字,可以认为msg就相当于DOM事件中的click事件名称,事件对象就是具体某个click事件。可以看到,emitter还发出了一个名为msgs的事件,这个事件并没有计入source$,因为fromEvent的第二个参数明确指定只接受msg类型的事件。

参考数据:《深入浅出RxJS》

RxJS——创建数据流相关推荐

  1. 思博伦Spirent TestCenter - 使用向导模式创建数据流_双极未来

    打开Spirent TestCenter Application测试软件,从菜单栏选择按钮Chassis->Port Reservation连接机框并占用端口. 从菜单栏选择按钮Wizards ...

  2. RxJS——异步数据流的响应式编程库(适合新手入门)

    文章目录 RxJS概述 Redux VS RxJS RxJS核心概念解析 热观察和冷观察 merge/combine合流 RXJS6 的变化 RxJS概述 RxJS 全称 Reactive Exten ...

  3. angular之Rxjs异步数据流编程入门

    Rxjs介绍 参考手册:https://www.npmjs.com/package/rxjs 中文手册:https://cn.rx.js.org/ RxJS 是 ReactiveX 编程理念的 Jav ...

  4. RxJS实践,Vue如何集成RxJS

    一. 本文章不会对RxJS的原理进行讲解,仅讨论如何在vue中对RxJS进行集成 1.30天精通 RxJS 这是一个台湾开发者编写的关于RxJS的教程,教程涉及到原理解析.简易实现,以及常用opera ...

  5. Angular-Observable和RxJS

    参考文章:介绍RxJS在Angular中的应用 一.可观察对象(Observable) 可观察对象支持在应用中的发布者和订阅者之间传递消息. 可观察对象是声明式的--也就是说,发布者中用于发布值的函数 ...

  6. bash: 无法为立即文档创建临时文件: 权限不够_世界顶级Linux大牛耗时三年总结出3000页Linux文档...

    众所皆知的,Linux的核心原型是1991年由托瓦兹(Linus Torvalds)写出来的,但是托瓦兹为何可以写出Linux这个操作系统?为什么它要选择386的计算机来开发?为什么Linux的发展可 ...

  7. node-red教程2 第一条数据流

    2.1 Node-RED的结构框架 Node-Red由两部分组成.一部分是用户可见的数据流的编辑界面,另一部分是数据流的执行.刚刚在PowerShell中打开node-red时,我们已经见过了数据流的 ...

  8. ASP.NET Web API 应用教程(一) ——数据流使用

    相信已经有很多文章来介绍ASP.Net Web API 技术,本系列文章主要介绍如何使用数据流,HTTPS,以及可扩展的Web API 方面的技术,系列文章主要有三篇内容. 主要内容如下: I  数据 ...

  9. python创建excel_python自动生成excel(xlwt库)

    # coding: utf-8import web import json import datetime import xlwt import StringIO # 如果不在前端调用接口,如下web ...

最新文章

  1. mysql filter_MySQL 过滤复制+复制映射 配置方法
  2. python print 不能立即打印输出 解决方法
  3. php错误提示:date_default_timezone_get
  4. 安卓惯性传感器(二)
  5. [architecture]-ARM AMBA/AXI/ACE/LITE总线介绍
  6. 数据结构之字典序全排列
  7. 抹掉所有内容和设置 macOS Monterey这个新功能太好用
  8. 【分享】Lucene.Net的中文分词组件AdvancedChineseAnalyzer
  9. MyCat分布式数据库集群架构工作笔记0001---Mycat简介
  10. Linux Guard Service - 守护进程分裂
  11. [译]Windows 登录时间太长的案例
  12. 如何全面认识大数据分析的基础知识
  13. python绘制玫瑰花代码视频_python turtle玫瑰花绘制效果和源代码
  14. 初始MySQL增删改查数据
  15. 如何实现Windows Network所有会话的限制登录和访问控制
  16. HBase跨版本数据迁移总结
  17. android 图片合成pdf文件,教你怎么把多张图片合成一个pdf文件
  18. EIA/TIA布线标准(568A、568B)
  19. 如何建立个人网站服务器篇
  20. Matlab 动态心形线GIF图

热门文章

  1. QT 静态库和动态库的使用方法
  2. 记录Android开发过程中遇到的疑难问题
  3. 【笔记分享】十一种滤波算法
  4. (转)十分钟搞懂Lombok使用与原理
  5. SSM《程序设计基础》课程答疑系统的设计与实现 毕业设计-附源码261620
  6. 【蓝桥杯嵌入式】第十二届蓝桥杯嵌入式省赛程序设计试题以及详细题解
  7. 我的计算机课1000字,电脑课讲话反思1000字(共9篇).docx
  8. 小学生心理测试软件,小学生趣味心理测试:性格测试
  9. word文档怎么翻译成中文?不妨试试这几个方法
  10. 计算机网络技术与应用的ppt,计算机网络技术与应用.ppt