Zademy

Vanilla JavaScript 的 RxJS 基础课程

RxJS; JavaScript; ReactiveProgramming
words 字

1. 什么是响应式编程

响应式编程处理的是随时间变化的数据流。

鼠标点击是事件,输入框打字是事件,HTTP 响应是异步事件。核心思路:别反复轮询 "数据到了没",数据来的时候你直接响应就行。

2. 什么是 RxJS

RxJS 是个 JavaScript 库,用 Observable 来组合异步和事件驱动的逻辑。

快速安装

使用 npm:

npm install rxjs

使用 CDN:

<script src="https://unpkg.com/rxjs@7/dist/bundles/rxjs.umd.min.js"></script>

Vanilla JS 基础结构

目录就三个文件:index.html、app.js、styles.css(可选)。

3. Observable

Observable 是数据源,可以在时间轴上发出 0 个、1 个或多个值。

const { of, from, interval } = rxjs;

of(1, 2, 3).subscribe(console.log); // 1, 2, 3
from(["A", "B"]).subscribe(console.log); // A, B

fromEvent

const { fromEvent } = rxjs;
const button = document.getElementById("btn");

const click$ = fromEvent(button, "click");
const sub = click$.subscribe(() => console.log("click"));

订阅与取消订阅

const { interval } = rxjs;

const sub = interval(1000).subscribe(v => console.log("tick", v));
setTimeout(() => sub.unsubscribe(), 5000);

4. 基础操作符

操作符就是转换或过滤 Observable 值的函数。

const { of } = rxjs;
const { map, filter, take } = rxjs.operators;

of(1, 2, 3, 4, 5)
	.pipe(
		filter(n => n % 2 === 1),
		map(n => n * 10),
		take(2)
	)
	.subscribe(console.log); // 10, 30

本课程用到的核心操作符分几类:创建(of, from, interval, timer)、转换(map, filter)、组合(merge, concat)、过滤(take, first, debounceTime)。

5. DOM 事件处理

点击计数器

const { fromEvent } = rxjs;

const btn = document.getElementById("btn");
const output = document.getElementById("output");
let count = 0;

fromEvent(btn, "click").subscribe(() => {
	count += 1;
	output.textContent = `Clicks: ${count}`;
});

实时搜索(基础)

const { fromEvent } = rxjs;
const { map, debounceTime } = rxjs.operators;

const input = document.getElementById("search");

fromEvent(input, "input")
	.pipe(
		map(e => e.target.value.trim()),
		debounceTime(300)
	)
	.subscribe(term => console.log("Search:", term));

6. 异步处理

Observable vs Promise

Promise 一般只返回一个未来值。Observable 可以持续发出多个值,而且能 unsubscribe 取消。这是本质区别。

使用 RxJS ajax 调用 API

const { ajax } = rxjs.ajax;

ajax
	.getJSON("https://jsonplaceholder.typicode.com/users")
	.subscribe({
		next: data => console.log("Users:", data),
		error: err => console.error("HTTP error:", err),
		complete: () => console.log("Completed")
	});

7. 错误处理与结束

const { of } = rxjs;
const { catchError, retry } = rxjs.operators;
const { ajax } = rxjs.ajax;

ajax
	.getJSON("https://api.example.com/data")
	.pipe(
		retry(2),
		catchError(err => {
			console.error("Request failed:", err);
			return of([]);
		})
	)
	.subscribe({
		next: data => console.log(data),
		complete: () => console.log("Finished")
	});

几个关键点:catchError 捕获并处理错误,retry 失败后重试,complete 流正常结束时触发,unsubscribe 手动停掉流。

8. 最佳实践

我的几条经验:无限流(interval、fromEvent)一定记得取消订阅,否则内存泄漏跑不掉。用 pipe 组织操作符,可读性好很多。别把复杂业务逻辑全塞进 subscribe,那会让代码很难维护。调试时 tap 是你的好朋友。

9. 最终项目(建议)

做个实时搜索迷你应用,把整个流程串起来。

步骤:创建输入框,fromEvent 监听输入,map + debounceTime 处理用户输入,ajax.getJSON 请求 API,渲染搜索结果,catchError 处理异常。

这个项目把课程基础知识全串了一遍。

10. 资源与下一步

官方文档:

推荐练习:用 interval 做计时器,做个 + / - 计数器,用公共 API 做实时搜索,练习 retry 的重试逻辑。

接下来可以学中级主题了:switchMap、mergeMap、Subject、进阶流组合。