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. 最佳实践

  • 对无限流(intervalfromEvent)要及时取消订阅。
  • 使用 pipe 组织操作符,保持可读性。
  • 不要把复杂业务全塞进 subscribe
  • tap 做调试更清晰。

9. 最终项目(建议)

实时搜索迷你应用:

  1. 创建输入框。
  2. fromEvent 监听输入。
  3. 使用 map + debounceTime
  4. ajax.getJSON 请求 API。
  5. 渲染搜索结果。
  6. catchError 处理异常。

这个项目可以把本课程的基础知识串成一个完整流程。

10. 资源与下一步

官方文档:

推荐练习:

  1. interval 做计时器。
  2. 做一个 + / - 计数器。
  3. 使用公共 API 做实时搜索。
  4. retry 练习重试逻辑。

下一步建议:

  • 学习中级主题:switchMapmergeMap、Subject、进阶流组合。