一、简介
RxJS 中可以使用构造函数创建可观察对象,但是这种方式明显的就是效率不高。于是 RxJS 针对不同的业务场景,实现了不同的可观察对象的创建操作符。
二、HTTP 请求
ajax
ts
import { ajax } from 'rxjs/ajax';
const ob$ = ajax('your_url').subscribe({})
const ob$ = ajax.getJSON('your_url').subscribe({})
const ob$ = ajax({
url: 'your_url',
method: 'POST',
headers: {
// your headers
},
body: {
// your body
}
}).subscribe({})
ajax 大致与 jQuery 时代的 ajax 使用基本一致,只是此处的 ajax 返回的是一个可观察对象。可以订阅这些可观察对象,获取到可观察对象的返回值。当然你可以在可观察对象的 pipe 中处理 ajax 的返回值,然后给订阅对象。
三、回调函数
- bindCallback
- bindNodeCallback
bindCallback
绑定回调函数,回调函数一般放在函数参数的最后位置,一个简单的示例:
ts
import { bindCallback } from 'rxjs';
const fnCb = (a,b, cb) => {
cb(a, b, {p: 1})
}
const boundFnCb = bindCallback(fnCb);
boundFnCb('3', 'c').subscribe({
next(v) {console.log(v)} // [ '3', 'c', { p: 1 } ]
})
自动执行 callback, 并且组合参数到数组中。
bindNodeCallback
绑定 node.js 中的回调函数,以 fs 为例,使用读取文件为例:
ts
import { bindNodeCallback } from 'rxjs'
import * as fs from 'fs'
const readFile = bindNodeCallback(fs.readFile)
readFile('./groupBy.js', 'utf-8').subscribe({
next(v) {
console.log(v) // 具体的文件的内容
}
})
四、时间
defer
延迟创建可观察对象,具有了懒的特性,只有在订阅了才创建。
ts
import { defer, of } from 'rxjs'
const d$ = defer(() => of(1,2,3))
d$.subscribe({
next(v) {console.log(v)}
})
of 操作符是一个创建型的操作符,直接使用 of 操作符,经过 defer 包裹之后,它就不会直接创建。当我们订阅之后,这个可观察对象才会被创建。
timer
timer 可以接受三个参数作为参数:
- dueTime: (number/Date) 等待时间
- intervalOrScheduler: 定时器或i这调度器
- scheduler: 可选的调度器
ts
import { timer, interval, of } from 'rxjs';
timer(1000)
.pipe(concatMap(() => of(1, 2, 3)))
.subscribe({
next(v) {console.log(v)}
});
timer(0, 1000).subscribe(n => console.log('timer', n));
interval
创建定时器可观察对象
ts
interval(1000).subscribe(n => console.log('interval', n));
实现与 timer 传递第二个参数时可以等价实现。
五、数据范围
range 指定范围
使用 range 操作符创建一个范围:
ts
import { range } from 'rxjs';
const numbers = range(1, 3);
numbers.subscribe({
next: value => console.log(value),
complete: () => console.log('Complete!')
});
此时与效果 of(1,2,3)
相似。
generate
range 是指定数字范围,generate 可以根据条件生成,执行不同的条件生成不同的数据。generate 可以接受的参数比较多,所以比 range 要更加灵活的生成数据。
- init: 指定初始状态
- condition: 终止生成条件
- iterate: 迭代步长函数
- resultSelector: 结果选择器
- scheduler: 调度器
ts
import { generate } from "rxjs";
const initialState = 0;
const condition = (x) => x < 10;
const iterate = (x) => x + 1;
const resultSelector = (x) => x;
const result = generate({ initialState, condition, iterate, resultSelector });
result.subscribe((x) => console.log(x));
💌💌💌由于 generate 一些写法已经被废弃,这里推荐使用对象的方法进行处理。
六、空值
empty 函数已经被废弃,使用 EMPTY 常量来代替,订阅时不会触发 next 方法,直接完成。
ts
import { EMPTY } from 'rxjs';
EMPTY.subscribe({
complete: () => console.log('Complete!')
});
因为不会触发 next 方法,这里就不写了,直接调用 complete。
七、错误处理
throwError 抛出错误可观察对象。参数是一个函数(推荐使用函数):
ts
import { throwError } from 'rxjs'
throwError(() => new Error('my error')).subscribe({
error(e) {console.log(e)}
})
当然 throwError 是处理错误的创建型函数,在 RxJS 也可以直接抛出一个 JavaScript 错误 new Error()
。
八、js 基础类型值(静态值)
of
ts
import { of } from 'rxjs';
// 情况
of(10, 20, 30).subscribe({next(v) { console.log(v) }) // 发出 10 发出 20 发出 30
of([10, 20, 30]).subscribe({next(v) { console.log(v) }) // 发出 [10 20 30]
of 特点是可以接受多个参数,每一个参数单独发射。
of 操作符值配合静态数据非常合适
。
from
from 与 of 不同的,from 接受一个迭代器 iterator 作为参数。当然数组是可以迭代的,下面以数组为例:
ts
import { from } from 'rxjs';
const array = [10, 20, 30];
const result = from(array);
from 解释一个迭代器参数,发射数据的时候,迭代数据发射。
九、事件(dom)
当然 RxJS 在处理 dom 事件时,也很方便,fromEvent 传递 dom 即可获取当前的 dom 的可观察对象。
fromEvent
ts
import { fromEvent } from 'rxjs';
const clicks = fromEvent(document, 'click');
clicks.subscribe(x => console.log(x));
fromEvent 指定 dom 和 dom 对应的事件作为可观察对象。
值得注意的是:fromEvent 是一个热可观察对象。事件有多个监听器,所有 fromEvent 算是热可观察对象,具有多播的特性。
fromEventPattern
fromEventPattern 是 fromEvent 底层版本,需要两个参数,一个是订阅、一个是移除订阅。
ts
import { fromEventPattern } from 'rxjs';
function addClickHandler(handler) {
// 订阅
}
function removeClickHandler(handler) {
// 移除订阅
}
const clicks = fromEventPattern(
addClickHandler,
removeClickHandler
);
clicks.subscribe(x => console.log(x));
明显 fromEventPattern 对于订阅有更多的操作性,如果是简单的 dom 操作使用 fromEvent 即可。
十、条件
iif
iif 是一个条件创建可观察对象。接受三个参数作为参数:
- 第一个是一个函数,返回一个布尔值
- 第二个参数:可观察对象
- 第三个参数:可观察对象
ts
import { iif, of } from 'rxjs';
let cond;
const who$ = iif(
() => cond,
of('first'),
of('second')
);
cond = false // 指定第一个参数的返回值
who$.subscribe({
next(v) {console.log(v)}
})
十一、小结
本文将创建型操作符大致分为 9 块内容,都是一些非常常见的 JS 适用场景,包含 dom 事件、ajax 请求、数据、条件判断、回调函数、错误等。这些操作符式为了方便在业务场景使用时快速的创建可观察对象。如果要熟练精通 RxJS 这些操作符的熟练程度要非常高。