在redux状态下放置返回promise的函数

时间:2016-07-01 21:41:45

标签: javascript reactjs redux es6-promise react-redux

我将解释为什么我想稍后这样做。 这是问题所在。我有一个返回如下承诺的函数:

const testFunc = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (Math.random() >  0.5) {
        resolve('succeeded');
      } else {
        reject('failed');
      }
    }, 1000);
  });
};

正如所料,我可以像这样调用它:

testFunc()
  .then((result) => console.log(result)) // 'succeeded'
  .catch((error) => console.log(error)); // 'failed'

或者将其分配给变量并像这样调用

const testFuncVar = testFunc;
testFuncVar()
  .then((result) => console.log(result)) // 'succeeded'
  .catch((error) => console.log(error)); // 'failed'

这些都是预料之中的。但是,一旦我将函数置于redux状态,然后从那里调用它,它就不再工作了。这就是我所做的(非常简化)。

const initialState = {testFunc: testFunc};
// redux reducer, action creator, etc.
...
...
// somewhere later. Here I'm using redux-thunk to access redux state
function testFunInState() {
  return (dispatch, getState) => {
    const {testFunc} = getState();
    // this is not working
    testFunc()
      .then((result) => console.log(result))
      .catch((error) => console.log(error));
  };
}

我得到的错误是_promise2 is not defined。请注意,变量名_promise2应该来自babel transpiler。如果我console.log(state.testFunc)console.log(testFunc),我得到了:

testFunc() {
  return new _promise2.default(function (resolve, reject) {
    if (Math.random() > 0.5) {
      resolve('succeeded');
    } else {
      reject('failed');
    }
  });
}

所以只要函数处于redux状态,Promise对象就会丢失?

但我确实找到了解决方法。如果我将功能更改为

const testFunc = (resolve, reject) => {
  setTimeout(() => {
    if (Math.random() >  0.5) {
      resolve('succeeded');
    } else {
      reject('failed');
    }
  }, 1000);
};

并将resolvereject作为参数传入,然后我很好。

// this works
new Promise((resolve, reject) => state.testFunc(resolve, reject))
  .then((result) => console.log(result))
  .catch((error) => console.log(error));

我想知道为什么返回承诺的函数一旦放入redux商店就不起作用,但没有返回承诺的函数有效?

现在我想以这种方式做到这一点。我想要实现的是拥有一个定期调度某些异步操作的作业队列,并根据结果(解决或拒绝)执行其他操作(如重试或发送通知)。我想在队列中动态添加/删除作业,因此很难有一个可以处理所有可能操作的reducer。感觉这是接近它的合理方式。我愿意接受建议。

2 个答案:

答案 0 :(得分:2)

随着更多的挖掘,我终于认为问题确实与redux或promise无关。这只是因为他们通过赋值给testFunc对象文字,将initialState添加到redux状态。当它以这种方式完成时,绑定将丢失,因此_promise2 is undefined错误。实际上,如果我动态地将testFunc添加到redux状态(例如通过动作创建器和减速器),绑定得到保留,一切正常。以下是问题https://stackoverflow.com/a/2702028/4401488的更详细说明。

仅供参考,以下是通过reducer

testFunc添加到redux状态的代码
const initialState = {};
// redux reducer
export default function jobReducer(state = initialState, action = {}) {
  switch (action.type) {
    case ADD_JOB:
      return {job: action.job};
    default:
      return state;
  }
}

// action creator
export function addJob(job) {
  return {
    type: ADD_JOB,
    job: job
  };
}
...
// add testFunc to redux state via action creator,
// I'm using redux-thunk here to access dispatch
function addTestFun() {
  return (dispatch) => {
    dispatch(addJob(testFunc));
  };
}
...
// invocation of testFunc. Here I'm using redux-thunk to access redux state
function testFunInState() {
  return (dispatch, getState) => {
    const {testFunc} = getState();
    // Now this is working
    testFunc()
      .then((result) => console.log(result))
      .catch((error) => console.log(error));
  };
}

答案 1 :(得分:1)

您需要将中间件与Redux一起使用,例如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)
);

然后写下你的动作:

const INCREMENT_COUNTER = 'INCREMENT_COUNTER';

function increment() {
  return {
    type: INCREMENT_COUNTER
  };
}

function incrementAsync() {
  return dispatch => {
    setTimeout(() => {
      // Yay! Can invoke sync or async actions with `dispatch`
      dispatch(increment());
    }, 1000);
  };
}

您也可以尝试使用Redux-Promise