I'll explain why I want to do this later. Here is the problem. I have a function that returns a promise like below:
const testFunc = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('succeeded');
} else {
reject('failed');
}
}, 1000);
});
};
As expected, I can invoke it like this just fine:
testFunc()
.then((result) => console.log(result)) // 'succeeded'
.catch((error) => console.log(error)); // 'failed'
Or assign it to a variable and call it like this
const testFuncVar = testFunc;
testFuncVar()
.then((result) => console.log(result)) // 'succeeded'
.catch((error) => console.log(error)); // 'failed'
These are all expected. However, once I put the function in redux state, then invoke it from there, it doesn't work anymore. Here is what I did (grossly simplified).
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));
};
}
The error I got was _promise2 is not defined
. Note that the variable name _promise2
should be from babel transpiler. If I console.log(state.testFunc)
or console.log(testFunc)
, I got:
testFunc() {
return new _promise2.default(function (resolve, reject) {
if (Math.random() > 0.5) {
resolve('succeeded');
} else {
reject('failed');
}
});
}
So somehow the Promise
object got lost whenever the function is put in redux state?
But I did find a workaround. If I change the function to
const testFunc = (resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve('succeeded');
} else {
reject('failed');
}
}, 1000);
};
And call it with resolve
and reject
passed in as parameters, then I'm good.
// this works
new Promise((resolve, reject) => state.testFunc(resolve, reject))
.then((result) => console.log(result))
.catch((error) => console.log(error));
I'm wondering why a function that returns promise doesn't work once it's put in redux store, but one without returning promise works?
Now onto why I want to do it this way. What I'm trying to achieve is to have a job queue that periodically dispatch some async actions, and depending on the result (resolve or reject), does something else (like retry, or send out notification). I want to dynamically add/remove jobs to and from the queue, therefore it's hard to have a reducer that can handle all possible actions. It feels like this is a reasonable way to approach it. I'm open to suggestions.
Using Redux-Promise in React AppYou can use a promise to represent a value based on the request data, either the resolved value or why the request is unresolved. JavaScript uses promises subscribed by a function, and the same function knows how to request status and resolve or reject the promise.
dispatch returns something that is not a promise.
As it turns out, Redux already has an official version of that "async function middleware", called the Redux "Thunk" middleware. The thunk middleware allows us to write functions that get dispatch and getState as arguments.
The connect() function connects a React component to a Redux store. It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store.
With a bit more digging, I finally figured that the problem really has nothing to do with redux or promise. It's simply because they way testFunc
getting added to redux state through assignment to initialState
object literal. When it's done this way, the binding is lost, hence the _promise2 is undefined
error. Actually if I add testFunc
to redux state dynamically (e.g. via action creator and reducer), the binding got preserved and everything works just fine. Here is a more detail explanation of the issue https://stackoverflow.com/a/2702028/4401488.
Just for reference, here is the code for adding testFunc
to redux state via reducer
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));
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With