Reputation: 8462
I have a promise that handles a HTTP request performed over a Web API:
promise = promise.then(r => {
// ...
}, error => {
if (error.status == 404) {
// Here I can fix an error and continue properly
} else {
// Here the error should be propagated further in the promise
}
}
// later in the code:
promise.catch(r => { /* More error handling */ } );
Later in the code this promise is chained to more error checks.
In case of a 404 error, I can actually "fix" a problem, and I don't want the other handler to trigger. I'd rather want to make the promise a success in this case. How can I do that?
A bit more code to explain my case more deeply:
refresh() {
this.refreshAsync().catch(r => {
// Show error to the user.
notifications.showError("Unexpected error happened");
});
}
async refreshAsync() {
// Here goes a lot of vue-resource calls to gather the necessary data for a view. They are chained with `await`. Only one of them:
await this.$http.get(url).then(r => {
this.data = r.data;
}, error => {
// 404 is actually a legit response for API to return, so the user notification above should not be shown
if (error.status == 404) {
// handle successfully
} else {
// propagate an error, so the handler above could show a warning to the user.
}
});
}
Upvotes: 9
Views: 4124
Reputation: 4537
If you need to propagate your success flow when you "fix" it, I can think of two approaches here,
promise
in another promise and call resolve(yourValue)
on error 404. But then this will mean you'll have to change your further chained logics on the promise
object, but on the contrary this will give you more flexibility.Hope it helps ;)
EDIT
After seeing your code, I still feel it is achievable by what I have mentioned before. You can do something on the lines of -
refreshAsync = async () => {
return new Promise((resolve,reject)=>{
await this.$http.get(url).then(r => {
this.data = r.data;
}, error => {
if (error.status == 404) {
resolve(); //populate this with your desired value
} else {
reject();
}
})
}
Upvotes: 2
Reputation: 41533
If you're using the standard Promise
implementation, you can simply just throw an error and then it will be returned as a failed promise result to the next catch
method:
// let's assume we have the following async operation
const somePromiseCall = () =>
new Promise(resolve => setTimeout(() => resolve(), 1000))
somePromiseCall()
.then(() => {
if (Math.random() > .5) {
throw 'this is the error message'
}
return 'this is the result'
})
.then(result => console.log('success', result))
.catch(err => console.error('fail', err))
Another way to do this is just by returning another promise that you can immediately reject (either by returning new Promise((resolve, reject)=>reject('error message'))
or by returning the shorthand method Promise.reject('error message')
:
// let's assume we have the following async operation
const somePromiseCall = () =>
new Promise(resolve => setTimeout(() => resolve(), 1000))
somePromiseCall()
.then(() => {
if (Math.random() > .5) {
return Promise.reject('error message')
}
return 'this is the result'
})
.then(result => console.log('success', result))
.catch(err => console.error('fail', err))
The reason why the second version works is because any return value from a then
or catch
method is wrapped in a promise and passed on so you can chain then
calls.
Knowing this, if you return a value, the then
method, behind the scenes, actually returns something like Promise.resolve(returnValue)
, so that you can do chaining:
somePromiseCall()
.then(result => result + 1)
.then(newResult => /* newResult === result + 1 */)
That's why the above snippet is similar to this one:
somePromiseCall()
.then(result => Promise.resolve(result + 1))
.then(newResult => /* newResult === result + 1 */)
Having this in mind, you can also return a rejected promise that actually can be caught with the catch
method:
somePromiseCall()
.then(result => Promise.reject('reason'))
.catch(err => console.log('error', err))
Upvotes: 1
Reputation: 828
You can simply return a reject/resolve
if(error.status == 404)
return Promise.resolve('OK')
else
return Promise.reject('fail')
I made an example showing how this work, just for this case:
httpRequest = function () {
return new Promise(function (res, rej) {
let status = (Math.round(Math.random()) === 1) ? 200 : 404;
console.log(status)
if (status === 200)
return res({ status })
else
return rej({ status })
})
}
let promise =
httpRequest()
.then(res => Promise.resolve('success'))
.catch(e => {
if (e.status === 404)
return Promise.resolve('success')
else
return Promise.reject('failed')
})
promise
.then(res => {
console.log(res)
})
.catch(e => {
console.log('this should not happen')
})
Upvotes: 3