5月27日 21:45

RxJS 中的 Observable 和 Promise 有什么区别?

核心答案

Observable 和 Promise 都是处理异步操作的工具,关键区别在四个字:单值/多值、惰性/急切、可取消/不可取消、单播/多播

维度PromiseObservable
值的数量只能 resolve 一次可以 next 多次
执行时机创建即执行(eager)订阅才执行(lazy)
取消无法取消unsubscribe() 取消
多播同一 Promise 多次 then 共享同一结果默认冷 Observable,每次订阅独立执行
错误重试需手动包装retry 操作符一行搞定
操作符then/catch/finallymap、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 原生支持:

javascript
const 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 统一了这些模型。
标签:Rxjs