【问题标题】:Put function that returns promise in redux state将返回 promise 的函数置于 redux 状态
【发布时间】:2016-07-01 21:41:44
【问题描述】:

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

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');
    }
  });
}

所以Promise 对象在函数处于 redux 状态时会以某种方式丢失?

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

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));

我想知道为什么一个返回 promise 的函数在放入 redux store 后就不起作用,而一个没有返回 promise 的函数起作用?

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

【问题讨论】:

  • 这很令人困惑,尤其是错误,因为在发布的代码中似乎没有 _promise2 ...任何东西 ..?
  • 我高度怀疑您遇到的错误未在此 sn-p 中显示。函数返回什么并不重要,您只是在存储中存储对它的引用。
  • @adeneo _promise2 应该来自 bable 转译器。我已编辑问题以使其更清楚。
  • statestate上贴上你标记promise func的reducer代码
  • @lux,我正在使用 redux-thunk 访问状态中的testFunc。我对原始问题进行了额外的编辑。 @AlexG,我有同样的理解,返回的内容并不重要,因为我只是存储对函数的引用。但不知何故,每当我在函数中有 new Promise 时,它就会停止工作。

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


【解决方案1】:

通过更多的挖掘,我终于发现这个问题真的与 redux 或 promise 无关。这仅仅是因为他们通过分配给initialState 对象字面量来将testFunc 添加到redux 状态。以这种方式完成时,绑定丢失,因此出现_promise2 is undefined 错误。实际上,如果我动态地将 testFunc 添加到 redux 状态(例如,通过 action creator 和 reducer),绑定得到保留,一切正常。这里有更详细的问题解释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));
  };
}

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我正在使用 redux thunk。但在这种情况下,我的目标不是调度一系列异步操作。相反,我想动态添加或删除 thunk(返回承诺的函数)到 redux 状态,并让调度程序定期调度它们。
    • 存储旨在跟踪应用程序状态/数据,而不是存储功能。您能否在您的商店中有一个引用 thunk 的数据结构,然后让调度程序根据您的商店中的内容调用它们?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 2017-08-17
    相关资源
    最近更新 更多