Redux-Promise拒绝Promise仍被分发至Reducer?与官方描述不符的原因咨询
首先先明确Redux-Promise官方文档的描述:
如果接收到Promise,会分发该Promise的resolved值;若Promise被rejected,则不会分发任何内容。
但你遇到的情况是rejected的Promise居然被reducer收到了,这确实和官方描述不符,我之前也碰到过类似的问题,主要是下面几个常见原因:
1. 你大概率搞混了两个不同的Promise中间件!
这是最常见的坑——很多开发者会把redux-promise(官方维护的那个)和redux-promise-middleware(第三方中间件)搞混:
- 官方
redux-promise:它的逻辑确实如文档所说,当Promise rejected时,不会分发任何action,只会在控制台抛出一个未捕获的Promise错误(如果没加catch的话)。 redux-promise-middleware:这个第三方库的设计就不一样了,它会在Promise rejected时自动分发一个带_REJECTED后缀的action,比如你原本的action type是FETCH_DATA,它会dispatchFETCH_DATA_REJECTED,这时候你的reducer自然会收到这个action。
你可以去检查你的store.js里的中间件配置,看看导入的是哪个库——比如redux-promise的导入通常是import promise from 'redux-promise',而redux-promise-middleware是import promiseMiddleware from 'redux-promise-middleware',两者的使用方式也不一样。
2. 使用了旧版本的Redux-Promise
早期版本的redux-promise(比如v0.4.x及更早)在错误处理上有漏洞。当Promise被reject且没有被catch时,中间件可能没有正确拦截这个错误,导致这个rejected的Promise被当作原始action直接传递给了reducer。
你可以打开package.json看看你的redux-promise版本,建议升级到最新稳定版(目前是v0.6.0左右),新版本修复了这类错误处理的问题。
3. Action Creator返回的不是标准结构
Redux-Promise只会处理两种情况的action:
- action本身就是一个Promise
- action是一个包含
payload属性的对象,且payload是Promise
如果你的action creator返回的是一个非标准结构(比如直接返回一个带promise属性的对象,而不是payload),Redux-Promise可能无法正确识别并处理这个reject,反而把整个对象传递给了reducer。
举个错误的例子:
export const fetchData = () => { const failedPromise = new Promise((resolve, reject) => { reject(new Error('Oops, failed!')); }); // 错误:这里返回的是{ promise }而不是标准的{ type, payload } return { promise: failedPromise }; };
正确的写法应该是这样:
export const fetchData = () => ({ type: 'FETCH_DATA', payload: new Promise((resolve, reject) => { reject(new Error('Oops, failed!')); }) });
4. 未捕获的Promise错误打断了中间件逻辑
如果你的Promise被reject后没有任何catch处理,浏览器会抛出一个未捕获的Promise错误,这个错误可能会中断Redux-Promise的正常执行流程,导致中间件没来得及拦截这个action,反而把rejected的Promise直接传给了reducer。
你可以尝试在Promise里加个catch,或者全局监听unhandledrejection事件来捕获错误,看看能不能解决这个问题。
怎么验证?
你可以给store加上redux-logger中间件,看看实际dispatch的action是什么:
- 如果是官方
redux-promise正常工作,reject时不会有任何action被打印出来 - 如果是
redux-promise-middleware,会看到带_REJECTED后缀的action - 如果是版本问题,可能会看到一个rejected的Promise被当作action输出
内容的提问来源于stack exchange,提问作者farmcommand2

