RxJS中实现超时后触发错误的问题排查
问题:RxJS timeout操作符未触发预期的超时错误?
嘿,我一眼就看出问题所在了!你的代码里的Observable是同步执行的,这直接导致timeout操作符根本没机会发挥作用。
先看你的原代码:
getExec() { return _getObs().timeout(5000, new Error("timeout reached")); //5s timeout } _getObs() { return rx.Observable.create((sub) => { sub.onNext(executeVerySlowMethod()); sub.onCompleted(); }); }
问题根源
当你创建这个Observable的时候,executeVerySlowMethod()会立刻同步执行——不管它耗时多久,整个Observable的onNext和onCompleted都会在timeout操作符开始监听之前就全部完成了。简单说,timeout还没来得及启动,Observable已经结束了,自然不会触发超时错误。
修复方案
你需要把慢方法的执行改成异步,让Observable处于“活跃”状态,给timeout留足检测的时间。这里有两种常用的修改方式:
方式1:用setTimeout把执行放到异步队列
getExec() { return _getObs().timeout(5000, new Error("timeout reached")); } _getObs() { return rx.Observable.create((sub) => { // 把慢方法放到异步队列,让Observable不会立刻完成 setTimeout(() => { try { const result = executeVerySlowMethod(); sub.onNext(result); sub.onCompleted(); } catch (err) { sub.onError(err); } }, 0); }); }
方式2:用RxJS的defer+Promise包装同步方法
defer会在Observable被订阅时才执行内部的工厂函数,结合Promise可以轻松把同步方法转为异步流:
getExec() { return _getObs().timeout(5000, new Error("timeout reached")); } _getObs() { return rx.Observable.defer(() => { // 用Promise把同步方法包装成异步操作 return Promise.resolve().then(() => executeVerySlowMethod()); }); }
为什么这样能行?
修改后,Observable在订阅后不会立刻完成,而是会等待异步操作的结果。这时候timeout(5000)就能正常监控Observable的生命周期,如果5秒内异步操作还没完成,就会触发你定义的超时错误。
内容的提问来源于stack exchange,提问作者Héctor Valls
相关产品推荐
相关产品推荐

