使用.then控制异步redux操作中的操作顺序

时间:2017-06-01 20:44:19

标签: reactjs redux axios redux-thunk

我正在使用redux和thunk中间件做出反应。我想做一个异步请求,然后进行一系列操作。然后它会以同步顺序发生。我无法实现它。

以下是我尝试过的两种方式:

addStudent(name, campusId = undefined, view = 'students') {
        const creatingStudent = axios.post('/api/student', { name: name, campusId: campusId })
            .then(res => {
                return res.data
            })
            .then(student => {
               return store.dispatch(createStudent(student))
            })
            .then(()=> {return store.dispatch(getStudents())})
            .then(()=> {return store.dispatch(changeView(view))})         
            .catch(err => console.log(err))




addStudent(name, campusId = undefined, view = 'students') {
         const creatingStudent = axios.post('/api/student', { name: name, campusId: campusId })
             .then(res => {
                 return res.data
             })
             .then(student => {
                store.dispatch(createStudent(student))
               store.dispatch(getStudents())
                store.dispatch(changeView(view))
             })       
             .catch(err => console.log(err))
     }

我想要订单: 1)axios请求 2)调度createStudent 3)派遣getStudents 4)调度changeView

但我安装了日志中间件,3和4总是颠倒过来。另外,特别是对于第二个选项,我偶尔会遇到一个致命的错误,我认为这是由于其他一些顺序的反转造成的,但我无法准确说出是什么顺序,因为应用程序在记录之前就崩溃了。

我还尝试将调用链接到彼此之间,但这似乎不起作用,可能是因为他们没有返回承诺。

这是我的getStudents动作创建者:

export const getStudents = () => {
   return dispatch => {
    axios.get('/api/students')
      .then(response => {
        return dispatch(receiveStudents(response.data));
      });
  }
};

因为它击中服务器所以它需要更长的时间才有意义,但是如果store.dispatch没有返回一个承诺,我该怎么办呢?然后关闭它?什么是正确的方法?

编辑:这最初没有明确说明。我应该更明确地表示,我的挫败感是在receiveStudents()之前调度了changeViews(),而不是像我暗示的那样,在getStudents()之前调度了changeViews()。我不知道什么时候发送了getStudents()。

2 个答案:

答案 0 :(得分:0)

当我遇到这个问题https://github.com/reactjs/redux/issues/723时,这次谈话给了我很多帮助。

你应该可以用axios做这样的事情:

axios.all([
  store.dispatch(createStudent(student)),
  store.dispatch(getStudents()),
  store.dispatch(changeView(view))
]).then(() => {
  console.log('I did everything!');
});

您可以在每次发送链接操作后使用.then。我看到你说你试过了,但是这个设置直接来自redux-thunk中间件github自述文件,应该适用于你的案例https://github.com/gaearon/redux-thunk

return dispatch(
      makeASandwichWithSecretSauce('My Grandma')
    ).then(() =>
      Promise.all([
        dispatch(makeASandwichWithSecretSauce('Me')),
        dispatch(makeASandwichWithSecretSauce('My wife'))
      ])
    ).then(() =>
      dispatch(makeASandwichWithSecretSauce('Our kids'))
    ).then(() => //Chain another dispatch
      dispatch(getState().myMoney > 42 ?
        withdrawMoney(42) :
        apologize('Me', 'The Sandwich Shop')
      )
    );

答案 1 :(得分:0)

我正在回答我自己的问题。我问这个问题的方式的一个方面是误导。我想让我的学生改变视图后,我感到很沮丧,因为我在记录中间件中看到了CHANGE_VIEW,然后是RECEIVE_STUDENTS。但这与说3和4相反是不一样的。事实上,3和4按顺序发送。我现在明白了,因为getStudents()本身是一个异步操作, dispatching 它将在异步操作完成之前解析。因此,即使按顺序调度getStudents()和changeView(),也会在changeView()之后调度receiveStudents()。在我的例子中,如果我想在receiveStudents()之后调度changeView(),我需要在getStudents()中调度(changeView())。

这是完成我想要的重构代码:

addStudent(student, view = 'students') {
    const creatingStudent = axios.post('/api/student', student)
        .then(res => res.data)
        .then(student => store.dispatch(createStudent(student)))
        .then(()=> store.dispatch(getStudents(view)))      
        .catch(err => console.log(err))
}



const getStudents = (view) => {
   return dispatch => {
     axios.get('/api/students')
       .then(res => dispatch(receiveStudents(res.data)))
       .then(()=>dispatch(changeView(view)))
     }
   }