RxJS 是一个使用 observable 序列整合 异步和基于事件的程序 的 JavaScript 库。为了更好地处理事件序列,RxJS 结合了观察者模式与迭代器模式和函数式编程与集合。
可以把 RxJS 看做对针对 事件 的 Lodash。
解决异步事件管理的一些重要概念:
- Observable:
- Observer:一个回调的集合,它知道如何监听
Observable
传递的值 - Subscription:表示
Observable
的执行,主要用于取消执行 - Operators:一种函数式编程风格的纯函数,可以用如
map
、filter
、concat
、reduce
等操作处理集合 - Subject:和
EventEmitter
一样,是将一个值或事件传递给多个Observer
的唯一方式 - Schedulers:用于控制并发的集中调度程序,支持在计算发生时进行协调,像
setTimeout
或requestAnimationFrame
及其它
# 示例
常见的注册事件监听的方法
代码语言:javascript复制document.addEventListener('click', () => {
console.log('click')
});
使用 RxJS 可以创建一个 Observable
实现
import { fromEvent } from 'rxjs';
fromEvent(document, 'click')
.subscribe(() => {
console.log('click')
});
# 纯函数
RxJS 的强大之处在于它能够使用 纯函数 产生值,这可以让代码更少出错。
通常,开发者会创建一个非纯函数,其他地方的代码可能会干扰状态。
代码语言:javascript复制let count = 0;
document.addEventListener("click", () => {
console.log(`Clicked ${ count} times`);
};
使用 RxJS 可以将状态隔离
代码语言:javascript复制import { fromEvent, scan } from 'rxjs';
fromEvent(document, 'click')
.pipe(
scan((count) => count 1, 0)
)
.subscribe(count => {
console.log(`Clicked ${count} times`);
});
scan
类似于 数组 的 reduce
方法,它接受一个暴露给回调的值,回调的返回值将作为下一次回调运行时暴露的下一个值。
# 流
RxJS 有很多的操作符,可以帮助开发者控制事件如何在 Observable
中流动。
通过原生 JavaScript 实现节流
代码语言:javascript复制let count = 0;
let rate = 1000;
let lastClick = Date.now() - rate;
document.addEventListener('click', () => {
if (Date.now() - lastClick >= rate) {
console.log(`Clicked ${ count} times`);
lastClick = Date.now();
}
});
使用 RxJS 实现
代码语言:javascript复制import { fromEvent, throttleTime, scan } from 'rxjs';
fromEvent(document, 'click')
.pipe(
throttleTime(1000),
scan((count) => count 1, 0)
)
.subscribe(count => {
console.log(`Clicked ${count} times`);
});
其他的流控制方法有 filter
(opens new window)、delay
(opens new window)、debounce Time
(opens new window)、take
(opens new window)、takeUntil
(opens new window)、distinct
(opens new window)、distinctUntilChanged
(opens new window) 等。
# 值
可以在 Observable
之间传递值。
使用原生 JavaScript 实现点击坐标 x 值累加
代码语言:javascript复制let count = 0;
const rate = 1000;
let lastClick = Date.now() - rate;
document.addEventListener('click', (event) => {
if (Date.now() - lastClick >= rate) {
count = event.clientX;
console.log(count);
lastClick = Date.now();
}
});
使用 RxJS 实现
代码语言:javascript复制import { fromEvent, throttleTime, map, scan } from 'rxjs';
fromEvent(document, 'click')
.pipe(
throttleTime(1000),
map(event => event.clientX),
scan((count, x) => count x, 0)
)
.subscribe(count => {
console.log(count);
});
其他的创建值的运算符有 pluck
(opens new window)、pairwise
(opens new window)、sample
(opens new window) 等。