5月27日 21:45
RxJS 中的 Observable 和 Promise 有什么区别?
核心答案
Observable 和 Promise 都是处理异步操作的工具,关键区别在四个字:单值/多值、惰性/急切、可取消/不可取消、单播/多播。
| 维度 | Promise | Observable |
|---|---|---|
| 值的数量 | 只能 resolve 一次 | 可以 next 多次 |
| 执行时机 | 创建即执行(eager) | 订阅才执行(lazy) |
| 取消 | 无法取消 | unsubscribe() 取消 |
| 多播 | 同一 Promise 多次 then 共享同一结果 | 默认冷 Observable,每次订阅独立执行 |
| 错误重试 | 需手动包装 | retry 操作符一行搞定 |
| 操作符 | then/catch/finally | map、filter、switchMap 等上百个 |
逐条展开
1. 单值 vs 多值
Promise 只能 resolve 一次,后续调用被忽略;Observable 通过 next 可以持续推送数据。
javascript// Promise — 只拿到 1 const p = new Promise(resolve => { resolve(1); resolve(2); // 无效 }); // Observable — 拿到 1, 2, 3 const obs$ = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); });
2. 惰性 vs 急切
Promise 构造函数里的代码在 new 时就跑了;Observable 的回调要等 subscribe 才执行。这意味着不订阅的 Observable 什么也不做,省资源。
3. 可取消
这是面试高频追问点。Promise 一旦创建就跑到完,想中途撤销只能用第三方库包装。Observable 原生支持:
javascriptconst sub = interval(1000).subscribe(x => console.log(x)); setTimeout(() => sub.unsubscribe(), 3000); // 3秒后停止
4. 冷 vs 热(单播 vs 多播)
冷 Observable 每次订阅都重新执行一遍;热 Observable(如 Subject)多个订阅者共享同一数据源。Promise 天然是"热"的——创建后结果确定,所有 then 拿到同一个值。
javascript// 冷 Observable — 两个订阅各跑一次 const cold$ = of(Math.random()); cold$.subscribe(v => console.log(v)); // 0.123 cold$.subscribe(v => console.log(v)); // 0.456(不同值) // 用 share() 变热 const hot$ = cold$.pipe(share());
5. 错误处理与重试
Promise 出错只能 catch 一次,重试要自己写循环。Observable 有 retry、retryWhen 等操作符,一行搞定指数退避重试。
javascript// Promise — 手动重试 function retryFetch(url, n) { return fetch(url).catch(err => n > 0 ? retryFetch(url, n - 1) : Promise.reject(err)); } // Observable — 一行重试 http.get(url).pipe(retry(3));
6. 操作符生态
Promise 只有 then 链,复杂异步编排(竞速、合并、去抖)要手写。Observable 有 switchMap、mergeMap、debounceTime、combineLatest 等操作符,声明式描述数据流。
面试追问方向
- 什么时候用 Promise 就够了? 单次异步请求、不需要取消、不需要流式处理——Promise 更简单。
- Observable 能完全替代 Promise 吗? 理论上可以(from(promise) 转换),但简单场景用 Observable 是过度设计。
- Angular 为什么选 Observable? HTTP 请求可能需取消(路由离开),表单值变化是流,组件生命周期也是流——Observable 统一了这些模型。