Reputation: 1195
I have a method which is firing two http requests to API to get the data.
getServerDetails(this.props.match.params.id) //1
.then(res => {
this.props.getServerDetailsAction({ success: true, data: res.data })
if (!_.isEmpty(res.data)) {
return getServerScomAlerts(res.data.ServerName) //2
}
})
.catch((err) => { //3
this.props.getServerDetailsAction({ success: false, error: err })
})
.then(res => {
if (!_.isEmpty(res)) {
this.props.getServerScomAlertsAction({ success: true, data: res.data })
}
})
.catch((err) => { //4
this.props.getServerScomAlertsAction({ success: false, error: err })
})
getServerDetails (1)
and getServerScomAlerts (2)
methods are returning promises. getServerScomAlerts (2)
is dependent on the result of getServerDetails (1)
The problem is that if error occurs in getServerScomAlerts (2)
the first catch block (3)
is executed. Is there a way how to get the data from the first method (1)
(without accessing store) and at the same time jump to the corresponding catch block (4)
if the error occurs?
Upvotes: 0
Views: 81
Reputation: 1381
Something like this might give you an idea how to achieve your goal. Instead of having nested then, you can use async/await and it waits for the result of each call before proceeding to the next:
export const actionCreators = {
myFunc: (param1, param2) => async (dispatch, getState) => {
try {
const response1 = await fetch(param1);
const data1 = await response.json();
const response2 = await fetch(param2);
const data2 = await response2.json();
} catch (err) {
console.log(err);
}
}
}
Upvotes: 1
Reputation: 1731
This is a good use case for .finally()
method, currently in draft specification according to the MDN. It allows you to remove duplication logic, by running the method after the promise is resolved or rejected.
As shown in the MDN example:
let isLoading = true;
fetch(myRequest).then(function(response) {
var contentType = response.headers.get("content-type");
if(contentType && contentType.includes("application/json")) {
return response.json();
}
throw new TypeError("Oops, we haven't got JSON!");
})
.then(function(json) { /* process your JSON further */ })
.catch(function(error) { console.log(error); /* this line can also throw, e.g. when console = {} */ })
.finally(function() { isLoading = false; });
If you want to use the feature right now, you can consider using Bluebird for your promise implimentation, which in some cases is faster, and should be easy to upgrade from as the method is standarized
Upvotes: 0
Reputation: 1422
It is really interesting with your problem since you want to do multiple actions which are slightly different from each other only :). I would rewrite as following
const getServerScomAlertsAction = (success, props) => (res) => {
success = success && !_.isEmpty(res);
props.getServerScomAlertsAction(success ? { success, data: res.data } : { success, error: res });
};
const getServerDetailsAction = (success, props) => (res) => {
props
.getServerDetailsAction(success ? { success, data: res.data } : { success, error: res })
.then(getServerScomAlertsAction(true, props))
.catch(getServerScomAlertsAction(false, props));
};
getServerDetails(this.props.match.params.id)
.then(getServerDetailsAction(true, this.props))
.catch(getServerDetailsAction(false, this.props));
Upvotes: 0