如何用Promise包裹Redux dispatch?resolve回调疑问解析
嘿,我来帮你把这个问题理清楚!
你对resolve的理解有点小偏差,我给你拆解清楚:
- 当你调用
resolve(xxx)时,不是先执行xxx再标记Promise完成,而是先把当前Promise的状态改成「已完成(fulfilled)」,同时把xxx作为Promise的结果传递给后续的.then()回调。 - 但有个特殊情况:如果
xxx本身是一个Promise,那当前Promise会“挂起”,等待这个传入的Promise完成后,才会跟着它的状态(成功/失败)走,再触发对应的回调。
回到你写的promisedDispatch:Redux的store.dispatch()本身是同步操作——它会立即更新Redux的state,然后返回你传入的action对象。所以你用Promise包裹它其实有点多余,但你的核心思路是对的:想确保dispatch完成后再执行setState,避免状态不一致。
先看你原来的代码:store.dispatch和this.setState是同步执行的,但React的setState本身是异步更新组件状态的,不过这里的竞态风险其实是「Redux state更新」和「组件state更新」的顺序问题。
你修改后的代码用.then()把setState放在promisedDispatch之后,确实保证了:只有当dispatch完成(Redux state已经更新),才会执行组件的setState,这就避免了两者顺序颠倒导致的状态不一致问题。
不过有个小优化点:既然store.dispatch是同步的,你其实不需要额外封装Promise,直接这么写就足够安全:
if (data !== null) { store.dispatch({ type: t.LOGGED_IN, token: data }); this.setState({ isReady: true, isLoggedIn: true }); }
因为dispatch同步完成后,Redux的state已经是最新的了,这时候调用setState完全不会有竞态问题。
但如果你的dispatch是异步的(比如用了redux-thunk、redux-saga这类中间件处理异步action,这时候dispatch可能返回一个Promise),那你原来的封装思路就很有必要了——或者更简单,直接用dispatch返回的Promise:
// 假设loginAction是一个返回Promise的异步action store.dispatch(loginAction(data)) .then(() => this.setState({ isReady: true, isLoggedIn: true }));
给你两个小例子,直观感受resolve的逻辑:
例子1:resolve普通值
const myPromise = new Promise((resolve) => { console.log('Promise内部代码执行'); resolve(console.log('调用resolve时,这个参数会立即执行')); }); myPromise.then(() => console.log('Promise完成后触发的回调'));
执行顺序是:
- 打印「Promise内部代码执行」
- 打印「调用resolve时,这个参数会立即执行」
- Promise状态变为已完成
- 打印「Promise完成后触发的回调」
例子2:resolve另一个Promise
const innerPromise = new Promise((resolve) => { setTimeout(() => resolve('内部Promise完成'), 1000); }); const myPromise = new Promise((resolve) => { console.log('外部Promise内部'); resolve(innerPromise); }); myPromise.then((val) => console.log(val));
执行顺序是:
- 打印「外部Promise内部」
- 等待1秒,innerPromise完成
- myPromise状态变为已完成,触发
.then() - 打印「内部Promise完成」
内容的提问来源于stack exchange,提问作者Ray Jonathan

