Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于在一个异步action中无法调用另一个异步action的问题(同步action可以) #12

Open
ckinmind opened this issue Feb 17, 2017 · 9 comments

Comments

@ckinmind
Copy link
Owner

背景是这样的:

给回复点赞的逻辑,是通过一个异步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;
@ckinmind
Copy link
Owner Author

上面触发另一个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

@Jeepeng
Copy link

Jeepeng commented Feb 19, 2017

需要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

@ckinmind
Copy link
Owner Author

@Jeepeng 感谢解答,还是有几个问题

  1. thunk中间件引入应该没问题,因为这里涉及两个异步action, 一个是starActions,一个是topicActions,而topicActions是starActions中调用的,实际执行过程中starActions这个异步action可以执行的,所以应该没问题

  2. 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)
);
  1. 我不是很清楚你的那种写法和我的写法有什么区别

最后还是感谢解答

@Jeepeng
Copy link

Jeepeng commented Feb 20, 2017

确实,redux@>=3.1.0可以这样用createStore,
但是看了一下redux源代码:报错位置
确实像是由于某种情况没有成功引入redux-thunk

@ckinmind
Copy link
Owner Author

@Jeepeng 感谢解答,我再研究研究

@WoolYang
Copy link

WoolYang commented Jun 2, 2017

我也遇到了同样的问题,请问怎么解决的?

@ckinmind
Copy link
Owner Author

ckinmind commented Jun 2, 2017

@WoolYang 这个是很久之前的问题了,我其实也忘了怎么解决的,估计我也没解决这个问题,现在我也不再使用redux, 而是使用另一个数据管理的库mobx, 强行安利,很好用,具体可以看我的这两个分享:

  1. apple-basket-redux

分别用redux和mobx实现了同一个demo, 你可以对比两种实现方式

  1. mobx-share

关于mobx的分享,帮助你快速掌握mobx

希望能对你有帮助

@RocketV2
Copy link

也遇到过此问题,不过我的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);
  		}
  	}
  }
}

如果我的理解有偏差,欢迎交流探讨~~

@ckinmind
Copy link
Owner Author

@RocketV2 感谢回复,但是这个问题已经是很久之前的问题了,而且现在我已经很久很久没有使用redux了,现在用的mobx, 很好用

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants