RxJS 是一个使用 observable 序列整合 异步和基于事件的程序 的 JavaScript 库。为了更好地处理事件序列,RxJS 结合了观察者模式与迭代器模式和函数式编程与集合。
可以把 RxJS 看做对针对 事件 的 Lodash。
解决异步事件管理的一些重要概念:
Observable
传递的值Observable
的执行,主要用于取消执行map
、filter
、concat
、reduce
等操作处理集合EventEmitter
一样,是将一个值或事件传递给多个 Observer
的唯一方式setTimeout
或 requestAnimationFrame
及其它常见的注册事件监听的方法
document.addEventListener('click', () => {
console.log('click')
});
使用 RxJS 可以创建一个 Observable
实现
import { fromEvent } from 'rxjs';
fromEvent(document, 'click')
.subscribe(() => {
console.log('click')
});
RxJS 的强大之处在于它能够使用 纯函数 产生值,这可以让代码更少出错。
通常,开发者会创建一个非纯函数,其他地方的代码可能会干扰状态。
let count = 0;
document.addEventListener("click", () => {
console.log(`Clicked ${++count} times`);
};
使用 RxJS 可以将状态隔离
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 实现节流
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 实现
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 值累加
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 实现
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) 等。