RXJS中fromPromise抛出错误未触发catchError操作符
问题根源:Promise的catch已经“吞掉”了错误
兄弟,你踩了一个很典型的Promise和RxJS错误处理边界混淆的坑,我给你掰碎了说:
核心逻辑拆解
你写的代码里,fromPromise接收的不是原始的runQuery() Promise,而是runQuery().catch(...)的结果——这是Promise自身的catch方法,不是RxJS的catchError!
当runQuery拒绝时,Promise的catch会:
- 捕获这个Promise的错误
- 返回一个新的resolved状态的Promise,它的resolve值就是你创建的
ErrorObservable实例
所以fromPromise拿到的是一个完全正常的、成功resolve的Promise,它会把这个Promise的resolve值(也就是那个ErrorObservable对象)作为普通的next值发射出去,自然会走到你的map操作符,根本不会触发RxJS的catchError——因为整个Observable流从始至终都没有发出error通知!
两种正确的写法
写法1:丢掉Promise的catch,用RxJS统一处理错误
这是最推荐的RxJS风格,把错误处理完全交给Observable流:
import { fromPromise } from 'rxjs/observable/fromPromise'; import { catchError, map } from 'rxjs/operators'; import { _throw } from 'rxjs/observable/throw'; const runQuery = () => Promise.reject(new Error('查询失败')); // 模拟会拒绝的Promise const source$ = fromPromise(runQuery({ d: 'g' })).pipe( map(result => /* 正常处理结果 */), catchError(err => { // 这里才会捕获到runQuery的错误 console.log('捕获到错误:', err); return _throw(err); // 或者返回一个兜底的Observable }) );
写法2:如果一定要用Promise的catch,要重新抛出错误
如果你因为某些原因必须保留Promise的catch,那不要返回ErrorObservable,而是重新抛出错误,这样Promise会保持rejected状态,fromPromise才会把它转换成Observable的error通知:
import { fromPromise } from 'rxjs/observable/fromPromise'; import { catchError } from 'rxjs/operators'; const runQuery = () => Promise.reject(new Error('查询失败')); const source$ = fromPromise( runQuery({ d: 'g' }).catch(err => { // 这里做一些Promise层面的前置处理,然后重新抛出 console.log('Promise层面先处理:', err); throw err; // 关键!让Promise保持rejected }) ).pipe( catchError(err => { // 现在RxJS的catchError就能捕获到了 console.log('RxJS捕获到错误:', err); return /* 兜底Observable */; }) );
关键区别要记牢
- Promise的
catch:处理Promise链的错误,返回的是resolved的Promise(除非你在里面重新抛出) - RxJS的
catchError:只处理Observable流中发出的error通知,只有当上游Observable出错时才会触发
内容的提问来源于stack exchange,提问作者29er
相关产品推荐
相关产品推荐

