将 returns promise 的函数置于 redux 状态
Put function that returns promise in redux state
稍后我会解释为什么要这样做。
这就是问题所在。我有一个函数 returns 像下面这样的承诺:
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);
};
然后用resolve
和reject
作为参数传入调用它,那我就很好了。
// this works
new Promise((resolve, reject) => state.testFunc(resolve, reject))
.then((result) => console.log(result))
.catch((error) => console.log(error));
我想知道为什么 returns promise 的函数一旦放入 redux store 就不能工作,但是没有返回 promise 的函数可以工作?
现在谈谈我为什么要这样做。我想要实现的是拥有一个作业队列,该队列定期调度一些异步操作,并根据结果(解决或拒绝)执行其他操作(如重试或发送通知)。我想动态地 add/remove 作业进出队列,因此很难有一个 reducer 可以处理所有可能的操作。感觉这是处理它的合理方法。我乐于接受建议。
你需要使用 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 或 promise 无关。这仅仅是因为他们通过分配给 initialState
对象字面量来将 testFunc
添加到 redux 状态。以这种方式完成后,绑定将丢失,因此会出现 _promise2 is undefined
错误。实际上,如果我动态地将 testFunc
添加到 redux 状态(例如,通过 action creator 和 reducer),绑定将被保留并且一切正常。这里有一个更详细的问题解释 .
仅供参考,这里是通过 reducer
添加 testFunc
到 redux state 的代码
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));
};
}
稍后我会解释为什么要这样做。 这就是问题所在。我有一个函数 returns 像下面这样的承诺:
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);
};
然后用resolve
和reject
作为参数传入调用它,那我就很好了。
// this works
new Promise((resolve, reject) => state.testFunc(resolve, reject))
.then((result) => console.log(result))
.catch((error) => console.log(error));
我想知道为什么 returns promise 的函数一旦放入 redux store 就不能工作,但是没有返回 promise 的函数可以工作?
现在谈谈我为什么要这样做。我想要实现的是拥有一个作业队列,该队列定期调度一些异步操作,并根据结果(解决或拒绝)执行其他操作(如重试或发送通知)。我想动态地 add/remove 作业进出队列,因此很难有一个 reducer 可以处理所有可能的操作。感觉这是处理它的合理方法。我乐于接受建议。
你需要使用 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 或 promise 无关。这仅仅是因为他们通过分配给 initialState
对象字面量来将 testFunc
添加到 redux 状态。以这种方式完成后,绑定将丢失,因此会出现 _promise2 is undefined
错误。实际上,如果我动态地将 testFunc
添加到 redux 状态(例如,通过 action creator 和 reducer),绑定将被保留并且一切正常。这里有一个更详细的问题解释 .
仅供参考,这里是通过 reducer
添加testFunc
到 redux state 的代码
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));
};
}