Redux Observable获取Epic中timeout操作符的正确放置位置问询
给Redux-Observable的API请求Epic添加超时控制
嘿,我看你在尝试给FETCH_DATA Epic加超时控制,但没达到预期效果。咱们先拆解你的代码,调整timeout的位置就能解决问题。
先看你现在的代码:
const fetchingEpic = (action$, store) => action$ .ofType('FETCH_DATA') .mergeMap(() => fromPromise( axios.post(`/url`, payload) ) .map(response => ({ type: 'FETCH_DATA_SUCCESS', data: response.data })) .timeout(5000) .catch(error => Observable.of({ type: 'FETCH_DATA_ERROR', error })))
问题出在哪?
你的timeout位置其实差一点就对了,但有两个容易踩的坑:
- 如果你给
axios.post本身设置了超时(比如axios.post('/url', payload, { timeout: 6000 })),那axios的内置超时会先触发,RxJS的timeout就没机会生效了。 - 更关键的是:你的写法里,
timeout虽然在fromPromise之后,但没有用RxJS推荐的链式写法,而且错误捕获的范围可能没覆盖到超时场景,导致超时后没触发你期望的FETCH_DATA_ERROR动作。
调整后的正确写法
我给你改成标准的RxJS链式写法,同时把timeout放在最适合的位置:
import { Observable } from 'rxjs'; import { fromPromise } from 'rxjs'; import { timeout, map, catchError } from 'rxjs/operators'; const fetchingEpic = (action$, store) => action$ .ofType('FETCH_DATA') .mergeMap((action) => { // 这里别忘了从action里拿payload! const payload = action.payload; return fromPromise(axios.post(`/url`, payload)) .pipe( timeout(5000), // 从请求发起的那一刻就开始计时,5秒没响应直接触发超时 map(response => ({ type: 'FETCH_DATA_SUCCESS', data: response.data })), catchError(error => { // 还能区分是不是超时错误,做更精准的提示 const errorMsg = error.name === 'TimeoutError' ? '请求超时,请稍后重试' : error.message; return Observable.of({ type: 'FETCH_DATA_ERROR', error: errorMsg }); }) ); });
为什么这样改?
- 用
pipe链式调用是RxJS 5.5之后的标准写法,比嵌套式调用更清晰,也更容易排查问题。 timeout(5000)放在map之前,确保从请求发出去的瞬间就开始计时,只要5秒内没拿到响应,立刻触发超时错误进入catchError。- 我补了从action里取
payload的逻辑——你原来的代码里直接用payload变量大概率会报错,这可能也是你误以为超时没生效的原因之一!
另外提醒:如果你的项目用RxJS 6+,要确保操作符是从rxjs/operators导入的,而不是旧版本的rxjs/internal路径。
内容的提问来源于stack exchange,提问作者theseboys
相关产品推荐
相关产品推荐

