Every time if there is a 504 or 404 from an API call that I make I get the warning:
Possible Unhandled Promise Rejection (id: 12):
ReferenceError: Can't find variable: rej
Here is how I've coded:
function myFunction() {
const fullURL = 'URL_THAT_I_HIT'
const data = { "SOME_ID": ID_VALUE, }
return new Promise((res, rej) => {
try {
axios.post(fullURL, data).then((response) => {
res(response.data)
}).catch((error) => {
rej(error)
alert(error)
})
} catch (error) {
rej(error)
alert(error)
}
})
}
As per my understanding, I'm handling the rej and I've even double wrapped it so that I can throw rejection. Here is my code below where I'm calling myFunction
function fetchMyFunctionCall() {
if (res === undefined) {
alert("The call rejected")
} else {
console.log(res)
}
}
It shows the error message but I still see the warning. So, how do I handle the rejection properly in fetchMyFunctionCall?
I wasn't able to repro your error for the undefined variable but I think you can simplify your code like below:
function myFunction() {
const fullURL = 'URL_THAT_I_HIT'
const data = {
"SOME_ID": ID_VALUE,
}
return axios.post(fullURL, data).then((response) => {
return response.data
});
}
myFunction().then((data) => {
console.log(data)
}).catch((error) => {
console.log(error)
})
Axios itself returns a promise so no need of returning one explicitly.
Related
So I have this error handler middleware
class ErrorHandler extends Error {
constructor(statusCode, message) {
super();
this.statusCode = statusCode;
this.message = message;
}
}
const handleError = (err, res) => {
const { statusCode, message } = err;
res.status(statusCode).json({
status: "error",
statusCode,
message: "resource not found"
});
};
module.exports = {
ErrorHandler,
handleError
}
calling it in index.js
app.use((err, req, res, next) => {
handleError(err, res);
})
And I want to use it in all my methods, but I cant figure it out how to use it with catch. it does not seem very clear for me. For the 404 error works just fine, but If I'm trying to throw a 500 error, e.g. a ReferenceError I dont know how to use my function.
exports.getAll = function(req, res, next) {
User.find({})
.exec()
.then(users => {
if (users.length === 0) {
throw new ErrorHandler(404, "No users found");
} else {
res.json(users);
next;
}
})
.catch(error => {
res.status(500).send({
message: "Error finding users",
error: error
})
})
};
in .catch I want to use my error handler like I did in .then
in catch block, you can use next to go handle error like with next(err)
.catch(err=>{
let error = new ErrorHandler(500,"Error finding users");
next(error);
})
I am trying to set up a basic express app to get some API data using axios. I want to do things the right way but I am a bit lost with error handling. Ideally, if there is an error I want to communicate it to users which I could do if the API call was within it the route. But how do you do it if it's a separate function?
axios call function using async:
const getForm = async () => {
try {
const config = {
method: 'get',
url: 'https://api.something.org/niceform'
}
}
const response = await axios(config)
return response
} catch (error) {
return error.message
}
}
express route:
app.get('/niceform', async (req, res) => {
try {
const data = await getForm()
res.send(data)
} catch (error) {
???
}
})
If I understand it correctly the getForm() function will return either the response or the error and then the route will send whatever comes back. But then what does the route's catch block do and how should I use it?
Is this setup considered to be a good practice?
Any advice would be appreciated, I am still learning.
The catch block can be removed from the getForm function. An error will be caught anyways in the get route.
const getForm = async () => {
const config = {
method: 'get',
url: 'https://api.something.org/niceform'
};
const response = await axios(config);
return response;
}
Or the error can be caught inside getForm, in order to do something in that catch block, and be thrown:
const getForm = async () => {
const config = {
method: 'get',
url: 'https://api.something.org/niceform'
};
try {
const response = await axios(config);
return response;
} catch (err) {
// log the error
// add extra information to the error
// else
// (see the attached answer)
throw err;
}
}
Consequently, in the catch block in the get route, an error can be responded:
app.get('/niceform', async (req, res) => {
try {
const data = await getForm();
res.send(data);
} catch (error) {
res.error(error);
}
})
Reference:
https://stackoverflow.com/a/42171508/3563737
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw
How I can test in jest error case?
This is what I do:
I don't know if exist a method how to test this.
it ('the fetch fails and throw an error', async () => {
let response = {
status: 400,
body:
{
base : "RON",
date: "2019-08-01",
rates: {"error": 'error'}
}
};
fetch.mockReject(response)
try {
await fetchData();
} catch (e) {
expect(e).toEqual(response);
expect(await fetchData()).rejects.toThrow(e);
}
});
This is the code:
fetchData = async () => {
try {
const response = await fetch('https://api.exo/latest?base=RON');
const data = await response.json();
return data;
} catch (e) {
throw e;
}
};
expect.assertions to the rescue
it ('the fetch fails and throw an error', async () => {
expect.assertions(1);
let response = {
status: 400,
body: {
base : "RON",
date: "2019-08-01",
rates: {"error": 'error'}
}
};
fetch.mockReject(response)
try {
await fetchData();
} catch (e) {
expect(e).toEqual(response);
}
});
Test will fail once no exception is thrown. It has advantages over expect().toThrown:
you don't have to return Promise in your it() to make it work
it's easier to assert several related exceptions or sequential actions failed
it's easier to run partial matching over error caught(say with expect(e).toMatchObject({}) to skip some data you don't care about in current test case)
As for disadvantages - you have to update number manually after adding new assertions
You can do it in the following way:
async function throws () {
throw new Error('error')
}
test('promise throws', async () => {
await expect(throws()).rejects.toThrow()
})
test('the fetch fails with an error', async () => {
await expect(throws()).rejects.toThrow('error');
});
test('the fetch fails with an error', () => {
return expect(throws()).rejects.toMatch('error');
});
Read more docs.
I'm trying to set up a login action using Parser which returns an error if the authentification fails. Then I want to catch the errror and return it to the component where I display the error. However I always get an unhandled promise rejection.
I already tried different methods of rejecting or returning the error with no success.
reject(error) (recommended here Returning Promises from Vuex actions)
return reject(error)
return Promise.reject(error)
return Promise.reject(new Error(error))
or simply
return error
my actions:
actions: {
login(vuexContext, authData) {
console.log(authData.email)
Parse.User.logIn(authData.email, authData.password)
.then(user => {
vuexContext.commit('SET_USER', user)
})
.catch(error => {
console.error('Actions login - Error: ' + error)
reject(error)
})
}
my submit method:
onSubmit() {
this.$store
.dispatch('login', {
email: this.formData.email,
password: this.formData.password
})
.then(() => {
// ..
})
.catch(error => {
console.log('Catching' + error)
if (error.code == 101) {
this.errorMsg = 'Email oder Passwort falsch'
} else {
this.errorMsg =
'Entschuldigung, hier ist etwas schief gelaufen... Fehler: ' +
error.message
}
this.showError = true
this.$router.push('/sessions/new')
})
}
I would expect that the catch block in the onSubmit method catches the error .
you have to wrap the function return as a new promise.
actions: {
login(vuexContext, authData) {
return new Promise((resolve, reject) => {
console.log(authData.email)
Parse.User.logIn(authData.email, authData.password)
.then(user => {
vuexContext.commit('SET_USER', user)
resolve()
})
.catch(error => {
console.error('Actions login - Error: ' + error)
reject(error)
})
})
}
}
Id like to parse a vue resource data and send callback request depending on the data i receive from server , how would i achive this either using Vue.interceptors or .then callback :
methods : function(){
var resource = this.$resource('index');
resource.save({name: 'jimmy'}).then(function (response) {
//success callback
//resend request lets say if response.data == 'test'
}, function (response) {
// error callback
console.log(response)
});
}
Simply do the call again and make sure you return the Promise created by it:
methods: { someMethod: function(){
var resource = this.$resource('index');
resource.save({name: 'jimmy'})
.then(function (response) {
//resend request lets say if response.data == 'test'
if (response.data === 'test') {
// do request again and return the Promise.
return resource.save({name: 'jimmy'})
} else {
return Promise.resolve(response)
}
})
.then(function(response) {
// do something with response
// if there was a retry, `response` will be the second one.
})
.catch(function (error) {
// catch() will catch any errors in the Promise chain, not just the first level.
console.log(error)
});
}
}