RxJS HTTP request error handling - error-handling

In my project, I use RxJS to handle HTTP request. I came into a confusing point about the error handling part as following:
.switchMap((evt: any) => {
return http.getComments(evt.params)
.map(data => ({ loading: false, data }))
.catch(() => {
console.log('debugging here');
return Observable.empty();
});
})
in the above code, inside the switchMap operator, I use the http.getComments function to send request, which is defined by myself as following:
getComments(params) {
return Observable.fromPromise(
this.io.get(path, { params })
);
}
in this function, I use fromPromise operator convert the returned Promise to observable.
The problem is when HTTP request failed, the catch operator inside switchMap can not work, the debugging console can't output. So what's wrong with my code.

Do you really need to catch the error inside the switchMap anyway? You can handle your error in your source if you want.
.switchMap((evt: any) =>
http.getComments(evt.params).map(data => ({ loading: false, data }))
})
.subscribe(console.log, console.error);
Any way, your source code does not look to have any error, maybe your promise is not been rejected when the http fails and is just resolving with an error as a response (this is a guess because I've seen that before)

Your code should work. Here a simplified simulation, where http calls are substituted by a function which raises an error.
import {Observable} from 'rxjs';
function getComments(params) {
return Observable.throw(params);
}
const params = 'abc';
Observable.of(null)
.switchMap(_ => {
return getComments(params)
.map(data => ({ loading: false, data }))
.catch(err => {
console.log('debugging here', err);
return Observable.empty();
});
})
.subscribe(
console.log,
error => console.error('This method is not called since the error is already caught', error),
() => console.log('DONE')
)

Related

Vuejs error after passing axios interceptor

I have a problem that I can't solve with vue.js
I intercept queries that return an error (axios interceptor), and when it passes through this interceptor, the catch of the axios query is still taken into account.
Except that I wait for an error "error.api". which I don't receive, so it generates a console error.
Here is the code:
axios.interceptors.response.use(null, error => {
let path = '/login';
switch (error.response.status) {
case 401: path = '/login'; break;
case 404: path = '/404'; break;
}
store.commit('logout')
router.push(path);
return Promise.reject(error);
});
this error
2.js:376 Uncaught (in promise) TypeError: Cannot read property 'api' of undefined
And finally, the axios query and the error is generated by the last line (err.api[0])
deleteApi(id) {
this.$store.dispatch('deleteApi', id)
.then((res) => {
this.$toast.success(res.data.success)
this.deleteApiModal(id)
})
.catch(err => this.$toast.error(err.api[0]))
},
I finally found a solution but very dirty, which I find repetitive for not much.
It's on each call axios, to put a condition that checks if "err" exists...
I would have preferred to be able to interact on the interceptor to have managed this in only one place.
If someone has a better solution, I'll take it !
deleteApi(id) {
this.$store.dispatch('deleteApi', id)
.then((res) => {
this.$toast.success(res.data.success)
this.deleteApiModal(id)
})
.catch(err => { if(err) this.$toast.error(err.api[0]) })
},

Error handling in Vue JS - errors not caught

I have the following code:
fooService.update(this.bar).then( this.$emit('updated', this.updatedBar),).catch(err => {...
If an error is encountered, then the error is not caught. If I change the code to be:
fooService.update(this.bar).then(x => {this.$emit('updated', this.updatedBar);}).catch(err => {...
Then the error is caught and shows as expected. Can anyone explain to me what is going on and why it behaves in that way?
Edit
Underlying service code:
function updateBar(bar) {
return $http.put(`/api/bar/${bar.Id}`, bar);
}
So I still think the error is happening in the this.$emit the reason why, in
fooService.update(this.bar).then( this.$emit('updated', this.updatedBar),).catch(err => {
It has to evaluate the this.$emit first as you're setting the response from that function as the .then and not the call itself.
Proof of it doing that
function emit(){
console.log('emit')
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(emit()).catch( function() {console.log('carry on');})
notice how it logs "emit" first
Now if that errors you can see it doesn't hit the catch
function emit(){
console.log('emit')
throw new Error("bad")
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(emit()).catch( function() {console.log('carry on');})
So under the hood it's doing this (the simplest way I can think of)
emit()
try{
getService()
} catch{
...
}
Whereas if you actually pass the .then a function it changes the order of things
function emit(){
console.log('emit')
throw new Error("bad")
}
var promise = new Promise(function(resolve,reject){
setTimeout(() => {
console.log('promise is done')
reject();
}, 1000)
})
promise.then(() => {emit()}).catch( function() {console.log('carry on');})
and again under the hood it looks like this
try{
getService()
emit()
} catch{
...
}

Axios then function also does catch?

My post is successful, but I can't do anything in the then statement except console.log(); it always jumps to the catch.
axios.post('/group/15/discussion/'+ this.discussion.id+ '/schedule',this.form, {handleErrors:true})
.then(function(response) {
//this.form.valid = true;
console.log("success");
console.log('set form valid');
this.$refs['schedule-group-discussion-'+this.id].hide();
console.log('close modal');
/*this.$emit('updateDiscussion',response.data.discussion);
this.$toast.success(response.data.message,'Success!',{icon: 'fas fa-check-circle'});*/
})
.catch((error) => {
console.log("catch");
this.form.valid = false;
});
here is my console log in order:
success
set form valid
catch
What is wrong?
The problem is your scope of this. You're actually getting an error, cannot read property valid of undefined, but you didn't console.log(error). You need to use the fat arrow function in your .then() as well:
.then(function(response) {
to
.then((response) => {
Now this is scoped correctly.

HapiJS reply being called twice

I'm getting this error message with the snippet below
Unhandled rejection Error: reply interface called twice
Note that I'm using return for all the reply() interface
Locations
.findOne({
_id: request.params.id,
activationCode: payload.activationCode
}).then((location) => {
if (!location) {
return reply(Boom.notFound('Location not found'))
}
locationObject = location
if (payload.password !== payload.confirmPassword) {
return reply(Boom.badRequest('Password and Confirm Password must match'))
}
if (!payload.terms) {
return reply(Boom.badRequest('Must agree to Terms & Conditions'))
}
return newPaymentMethod.save()
}).then((paymentMethod) => {
.....
return user.save() // user is defined at .....
}).then(() => {
return reply({ token: helpers.createJwt(userObject) })
}).catch((err) => {
return reply(Boom.wrap(err))
})
Any help would be appreciated.
Looks like you get caught into this due to the incorrect use of promises. I guess you’re executing your snippet within a route handler where you’ve access to reply.
As you’re returning your responses within the promise chain, you both return the value to the next .then (promise) and also calling the reply from the outer scope.
I suggest you use a promise reject for errors so that you only need a single reply(Boom.method()) within the promise’s .catch().
Since you chain promises in the end
.then(() => {
return reply({ token: helpers.createJwt(userObject) })
}).catch((err) => {
return reply(Boom.wrap(err))
})
you might call reply twice if any of if conditions is true.
Easy solution would be to throw error in if condition is true - since there is already a Boom.wrap in catch block.

NodeJS Restify Nested Promise Error Handling

I have made API on restify for my product. I have installed loggly and newrelic for monitoring purposes.
Recently newrelic notified me that there was an error somewhere in my code.
app.get('/myroute', (req, res, next) => {
let payload = { /*...*/ };
return new Promise((resolve, reject) => {
/* some code */
return resolve();
})
.then(/* some promise */)
.then(() => {
/* some code */
sendEmail({params}); // some error was thrown from one of the promise chain
// inside this function...
return something;
})
.then(/* some promise */)
.then(() => {
res.send(something);
})
.catch(next);
});
The promise chain resolved perfectly fine and user gets proper response, because I didn't return the sendEmail function. And I don't want to, because I don't want the user to wait for the response for long.
function sendMail(params) {
return new Promise((resolve, reject) => {
/* some code */
return resolve();
})
.then(() => {
params.abc.replace('a', 'b'); // error thrown, cannot find replace of undefined.
return something;
});
}
newrelic caught the error, but loggly didn't. I already have restify's formatters setup but it won't be enough as the request was successfully served and didn't fall into .catch(next).
I don't want a solution to fix the sendMail function. I just want to log if there is a bug like this.
Is there anyway to catch and log this type of error without putting a .catch() to sendMail function?
I figured out. I was trying process.on('uncaughtException') to handled it.
But I came across process.on('unhandledRejection') which did the job!
https://nodejs.org/api/process.html#process_event_unhandledrejection