关于在一个异步action中无法调用另一个异步action的问题(同步action可以)
ckinmind opened this issue · 9 comments
背景是这样的:
给回复点赞的逻辑,是通过一个异步action, 在这个异步action中发送点赞请求,如果请求成功,则再调用获取当前topic的action, 这样可以重新加载一遍当前的topic以便使得点赞的更新显示出来,但是实际测试的过程中发现无法触发异步action中的异步action, 但是可以触发异步action中的同步action(另一个action)
starAction.js
import topicActions from './topicActions';
let starActions = {
starReply: function(replyId, replyLoginname){
return function (dispatch, getState) {
.....
fetch(`https://cnodejs.org/api/v1/reply/${replyId}/ups`, {
method: 'POST',
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: `accesstoken=${accessToken}`
})
.then(response => response.json())
.then(json => {
if (json.success) {
topicActions.testTecchingTopic(); //同步action, 测试通过
topicActions.fetchingTopic(); // 异步action, 没有响应
} else {
....
}
})
}
}
};
export default starActions;
topicActions.js
let topicActions = {
/** 加载topic异步操作*/
fetchingTopic: function (topicId) {
return function (dispatch, getState) {
console.log('这段话没打印出来了');
}
},
....
testTecchingTopic: () => {
console.log('这段话打印出来了');
}
}
;
export default topicActions;
上面触发另一个action的方式,是这样的
topicActions.testTecchingTopic(); //同步action, 测试通过
topicActions.fetchingTopic(); // 异步action, 没有响应
没有用dispatch方法,测试的结果是同步的能打印出结果,异步的没反应
如果使用dispatch
dispatch(topicActions.testTecchingTopic()); //同步
dispatch(topicActions.fetchingTopic(json)); //异步
同步的有打印结果
异步的报错:createStore.js?66b2:166 Uncaught (in promise) Error: Actions must be plain objects. Use custom middleware for async actions
需要dispatch的,看起来没什么问题。。。
从报错看来好像是引入thunk中间件没有成功
看了你的代码createStore函数用法错了:
const store = createStore(
reducer,
applyMiddleware(thunk)
);
应该:
// 调用 applyMiddleware,使用 middleware 增强 createStore:
const createStoreWithMiddleware = applyMiddleware(thunk)(createStore)
const store = createStoreWithMiddleware(reducer)
http://redux.org.cn/docs/api/createStore.html
http://redux.org.cn/docs/api/applyMiddleware.html
@Jeepeng 感谢解答,还是有几个问题
-
thunk中间件引入应该没问题,因为这里涉及两个异步action, 一个是starActions,一个是topicActions,而topicActions是starActions中调用的,实际执行过程中starActions这个异步action可以执行的,所以应该没问题
-
createStore的写法问题,我的写法是参照redux-thunk中的写法
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
// Note: this API requires redux@>=3.1.0
const store = createStore(
rootReducer,
applyMiddleware(thunk)
);
- 我不是很清楚你的那种写法和我的写法有什么区别
最后还是感谢解答
我也遇到了同样的问题,请问怎么解决的?
@WoolYang 这个是很久之前的问题了,我其实也忘了怎么解决的,估计我也没解决这个问题,现在我也不再使用redux, 而是使用另一个数据管理的库mobx, 强行安利,很好用,具体可以看我的这两个分享:
分别用redux和mobx实现了同一个demo, 你可以对比两种实现方式
关于mobx的分享,帮助你快速掌握mobx
希望能对你有帮助
也遇到过此问题,不过我的dispatch代码如下(成功执行):
ReduxStore.dispatch((dispatch,getState)=>{
// 做异步处理
setTimeout(()=>{
dispatch({type:'ADD_ITEM',text:val});
},2000)
})
官方给出的示例代码为:
function incrementAsync() {
return dispatch => {
setTimeout(() => {
// Yay! Can invoke sync or async actions with `dispatch`
dispatch(increment());
}, 1000);
};
}
尽管少了一层return 函数,但是确实能够获取到dispatch/getState,代码能够执行;redux-thunk的源码为:
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
将函数createThunkMiddleware改变一下,不难发现,我们通过dispatch传入的其实就是action,
如果action 类型为function,就会执行我们传入的函数,并且将dispatch/getState参数传入我们传入的函数中;
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) =>{
return (next) =>{
return (action) =>{
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
}
}
}
}
如果我的理解有偏差,欢迎交流探讨~~