I'm trying to throw an error from a function to another and to send a res.status(402). I put it in a try-catch block in the most basic way but still got the error.
: Unhandled promise rejection. This error originated either by throwing
inside of an async function without a catch block
this is the calling function:
const validateAction = async (req, res) => {
const { action, url, mail, orderId } = req.body;
try {
requestAction(action, url, mail, orderId);
} catch (err) {
console.error(err);
res.status(402).send({
status: 402,
error: "BUG",
});
}
this is the function I want from where I want to throw the error:
const requestAction = async (action, url, mail, oderId) => {
const result = actions.find((actionFind) => actionFind.action === action);
await axios({
//change the action to "add"
method: "post",
url: "XXXXXXXXXXXXXXXXXXXX",
data: {
key: "XXXXXXXXXXXXXXXXXXXXXXXX",
action: "XXXXX",
service: XXXXXX,
quantity: XXXXXXXXXX,
},
}).then(
(response) => {
if (response.data.error) {
sendLog(
` ${response.data.error} --- URL:${url} ACTION:${action} QUANTITY:${result.quantity} ID:${result.id}`,
"error"
);
// here is the throw that's not working---------------------------------------------
throw response.data.error;
//----------------------------------------------------------------------------------
} else {
sendMail(mail);
sendLog(
` Succesfully sent it --- URL:${url} ACTION:${action} QUANTITY:${result.quantity} ID:${result.id} To ${mail}`,
"info"
);
}
},
(error) => {}
);
};
I believe the answer is not complicated but I don't find it
You need to add an additional catch in the promise chain, for example like this:
const validateAction = async (req, res) => {
const { action, url, mail, orderId } = req.body;
requestAction(action, url, mail, orderId);
}
const requestAction = async (action, url, mail, oderId) => {
const result = actions.find((actionFind) => actionFind.action === action);
await axios({
//change the action to "add"
method: "post",
url: "XXXXXXXXXXXXXXXXXXXX",
data: {
key: "XXXXXXXXXXXXXXXXXXXXXXXX",
action: "XXXXX",
service: XXXXXX,
quantity: XXXXXXXXXX,
},
}).then(
(response) => {
if (response.data.error) {
sendLog(
` ${response.data.error} --- URL:${url} ACTION:${action} QUANTITY:${result.quantity} ID:${result.id}`,
"error"
);
throw response.data.error;
} else {
sendMail(mail);
sendLog(
` Succesfully sent it --- URL:${url} ACTION:${action} QUANTITY:${result.quantity} ID:${result.id} To ${mail}`,
"info"
);
}
}).catch(() => {
console.error(err);
res.status(402).send({
status: 402,
error: "BUG",
});
});
};
Basically need to add an
await So await requestAction(action, url, mail, orderId);
before the request action call.
Thanks to Felix Kling
Related
I'm doing requests to my API server to authenticate a user, that's not the problem. The problem is that I don't know why my async function doesn't return anything, and I get an error because the data that I want from this function is undefined.
Don't worry if the error management is ugly and in general I can do this better, I'll do that after fixing this problem.
Utils.js class
async Auth(username, password) {
const body = {
username: username,
password: password
};
let req_uuid = '';
await this.setupUUID()
.then((uuid) => {
req_uuid = uuid;
})
.catch((e) => {
console.error(e);
});
let jwtData = {
"req_uuid": req_uuid,
"origin": "launcher",
"scope": "ec_auth"
};
console.log(req_uuid);
let jwtToken = jwt.sign(jwtData, 'lulz');
await fetch('http://api.myapi.cc/authenticate', {
method: 'POST',
headers: { "Content-Type": "application/json", "identify": jwtToken },
body: JSON.stringify(body),
})
.then((res) => {
// console.log(res);
// If the status is OK (200) get the json data of the response containing the token and return it
if (res.status == 200) {
res.json()
.then((data) => {
return Promise.resolve(data);
});
// If the response status is 401 return an error containing the error code and message
} else if (res.status == 401) {
res.json()
.then((data) => {
console.log(data.message);
});
throw ({ code: 401, msg: 'Wrong username or password' });
// If the response status is 400 (Bad Request) display unknown error message (this sould never happen)
} else if (res.status == 400) {
throw ({ code: 400, msg: 'Unknown error, contact support for help. \nError code: 400' });
}
})
// If there's an error with the fetch request itself then display a dialog box with the error message
.catch((error) => {
// If it's a "normal" error, so it has a code, don't put inside a new error object
if(error.code) {
return Promise.reject(error);
} else {
return Promise.reject({ code: 'critical', msg: error });
}
});
}
Main.js file
utils.Auth('user123', 'admin')
.then((res) => {
console.log(res); // undefined
});
Your Async function must return the last promise:
return fetch('http://api.myapi.cc/authenticate', ...);
or await the result and return it:
var x = await fetch('http://api.myapi.cc/authenticate', ...);
// do something with x and...
return x;
Notice that you don’t need to mix promise syntax (.then) with await. You can, but you don’t need to, and probably shouldn’t.
These two functions do exactly the same thing:
function a() {
return functionReturningPromise().then(function (result) {
return result + 1;
});
}
async function b() {
return (await functionReturningPromise()) + 1;
}
await is not to be used with then.
let data = await this.setupUUID();
or
let data=null;
setupUUID().then(res=> data = res)
I would try something like this:
const postReq = async (jwtToken) => {
const body = {
username: username,
password: password,
};
try {
const res = await fetch('http://api.myapi.cc/authenticate', {
method: 'POST',
headers: { "Content-Type": "application/json", "identify": jwtToken },
body: JSON.stringify(body),
})
if (res) {
if (res.status == 200) {
return res.json();
} else if (res.status == 401) {
const data = res.json();
console.log(data.message)
throw ({ code: 401, msg: 'Wrong username or password' });
} else if (res.status == 400) {
throw ({ code: 400, msg: 'Unknown error, contact support for help. \nError code: 400' });
}
}
} catch (err) {
console.error(err)
}
};
const Auth = async (username, password) => {
const jwtData = {
"origin": "launcher",
"scope": "ec_auth"
};
try {
const req_uuid = await this.setupUUID();
if (req_uuid) {
jwtData["req_uuid"] = req_uuid;
const jwtToken = jwt.sign(jwtData, 'lulz');
return await postReq(jwtToken);
}
} catch (err) {
console.error(err);
};
}
I made a function on the node that makes a request to an api and I need to display this answer on screen, but it does not return anything, if I use console.log I can see the DATE in the answer, but if I give a RETURN RES.DATA it does not display anything, below is the function.
getAllPrices:
export default async function getAllPrices(vin) {
try {
await axios({
method: 'post',
url: url,
data: {
"Cap": 51136.47,
"DaysToFirstPayment": 30,
"OnePay":false,
"Rate":0.00006,
"ResidualValue": vin,
"Term":36,
"Type": 0
}
}).then(res => {
return res;
});
} catch (err) {
return err;
}
}
Vin parameter = 28319.22
Consuming function on the route:
// GetAllPrices
routes.get('/getAllPrices/:vin', async (req, res) => {
let { vin } = req.params;
return res.json(await getAllPrices(vin));
});
I have a change password function that hits this api for verification and I want to display an error if the current password is incorrect.
Any direction on how to go about this or if what I'm doing makes no sense please point me in the right direction if would be so kind, it would be greatly appreciated!
case "PUT":
try {
const validContact = await Contact.findOne({ _id: req.body.id });
const valid = bcrypt.compareSync(
req.body.currentPassword,
validContact.password
);
if (valid) {
const hashedPassword = bcrypt.hashSync(
req.body.newPassword,
bcrypt.genSaltSync()
);
const contact = await Contact.findOneAndUpdate(
{ _id: req.body.id },
{ password: hashedPassword },
{ new: true }
);
res.status(200).json({ success: true, data: contact });
}
res.status(400).json({ success: false });
} catch (error) {
res.status(400).json({ success: false });
}
break;
This is the function that calls the API upon form submission
const submitNewPassword = (submitNewPasswordForm, resetForm) => {
submitNewPasswordForm(); // <-- I want to put this in a conditional
resetForm();
setOpenPasswordPopup(false);
setNotify({
isOpen: true,
message: "Password updated successfully",
type: "success",
});
};
edit: submitNewPassword function
const submitNewPasswordForm = async () => {
try {
const res = await fetch(`${process.env.APP_DOMAIN}/api/${apiRoute}`, {
method: "PUT",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(values),
});
router.push(`${process.env.APP_DOMAIN}/`);
} catch (error) {
console.log(error);
}
};
Your submitNewPasswordForm doesn't return anything right now (well, it does, but it's just an empty Promise). To be able to check if it was a good request or not, you need to return something from it. Example:
const submitNewPasswordForm = async () => {
try {
const res = await fetch(`${process.env.APP_DOMAIN}/api/${apiRoute}`, {
method: "PUT",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(values),
});
// this check is also necessary; 400 isn't an exception that would get caught
if (!res.ok) {
throw new Error(res.statusText)
}
router.push(`${process.env.APP_DOMAIN}/`);
return true;
} catch (error) {
console.log(error);
// you could also re-throw the error, or return something else
return false;
}
};
Because it's an async function, it returns a Promise, so you need to get the return value out with a .then:
const submitNewPassword = (submitNewPasswordForm, resetForm) => {
submitNewPasswordForm()
.then((ok) => {
if (!ok) {
// show error
} else {
resetForm();
setOpenPasswordPopup(false);
setNotify({
isOpen: true,
message: "Password updated successfully",
type: "success",
});
}
})
};
If you re-throw the error in the first function, you could .catch it rather than checking for an ok value. You could also make the second function an async function if you wanted to. Example:
const submitNewPassword = async (submitNewPasswordForm, resetForm) => {
try {
submitNewPasswordForm()
// rest of the code
} catch (err) {
// show error
}
}
Whichever way you go, you'll have to return something from the function in order to know if it was a success or not.
You will need to declare the submitNewPassword with async as you will require to await.
Then I added the await before the submitNewPasswordForm() and the happy and unhappy path.
You can check the result here.
const submitNewPassword = async (submitNewPasswordForm, resetForm) => {
const response = await submitNewPasswordForm(); // <-- I want to put this in a conditional
if(response.status === 200){
const body = await response.json()
//happy path
}else
{
const bodyError = await response.json()
//unhappy path
}
resetForm();
setOpenPasswordPopup(false);
setNotify({
isOpen: true,
message: "Password updated successfully",
type: "success",
});
};
I'm trying to build a react native app and I can't seem to sign in. When I try I get a
'Signup Error - Something Went Wrong" general message.
I don't think my API is working and when I try it on postman I get a
404 message.
The URL should be fine so I'm not sure if it has something to do with a setting in the API backend or perhaps I'm botching my parameters somehow.
Here is my api.js code:
//const BASE_URL = "http://{ip address}:5000";
const BASE_URL = 'https://neighbor-hood.herokuapp.com';
export const api = async (url, method, body = null, headers = {}) => {
try {
const endPoint = BASE_URL.concat(url);
const reqBody = body ? JSON.stringify(body) : null;
const fetchParams = {method, headers};
if((method === "POST" || method === "PUT") && !reqBody) {
throw new Error("Request body required");
}
if(reqBody) {
fetchParams.headers["Content-type"] = "application/json";
fetchParams.body = reqBody;
}
const fetchResponse = await fetch(endPoint, fetchParams);
let text = ''
try{
console.log("fetchResponse ", fetchResponse)
text = await fetchResponse.text()
} catch (err){
console.log("Exception in turning text from response err", err)
}
return fetchResponse;
} catch (e) {
console.log("Exception ", e)
return e;
}
}
Here is my actions.js file that imports the api:
import {api} from "../service/api";
export const createNewUser = (payload) => {
return async (dispatch) => {
try {
dispatch({
type: "CREATE_USER_LOADING"
});
const response = await api("/user/create", "POST", payload);
if(response.success) {
dispatch({
type: "CREAT_USER_SUCCESS"
});
dispatch({
type: "AUTH_USER_SUCCESS",
token: response.token
});
dispatch({
type: "GET_USER_SUCCESS",
payload: response.responseBody
});
return response;
} else {
throw response;
}
} catch (error) {
dispatch({
type: "CREAT_USER_FAIL",
payload: error.responseBody
});
return error;
}
}
}
export const loginUser = (payload) => {
return async (dispatch) => {
try {
dispatch({
type: "LOGIN_USER_LOADING"
});
const response = await api("/user/login", "POST", payload);
if(response.success) {
dispatch({
type: "LOGIN_USER_SUCCESS",
});
dispatch({
type: "AUTH_USER_SUCCESS",
token: response.token
});
dispatch({
type: "GET_USER_SUCCESS",
payload: response.responseBody
});
return response;
} else {
throw response;
}
} catch (error) {
dispatch({
type: "LOGIN_USER_FAIL",
payload: error.responseBody
});
return error;
}
}
}
export const logoutUser = () => {
return async (dispatch, getState) => {
const state = getState();
try {
const {authReducer: {authData: {token}}} = state;
console.log(token);
const response = await api("/user/logout", "DELETE", payload);
console.log(response);
dispatch({
type: "USER_LOGGED_OUT_SUCCESS"
});
} catch (e) {
console.log(e);
}
}
}
This is what I get back in the console:
fetchResponse Response {
"_bodyBlob": Blob {
"_data": Object {
"blobId": "DC45F3C7-FB3E-4120-8B92-0AC798181824",
"name": "create.html",
"offset": 0,
"size": 232,
"type": "text/html",
},
},
"_bodyInit": Blob {
"_data": Object {
"blobId": "DC45F3C7-FB3E-4120-8B92-0AC798181824",
"name": "create.html",
"offset": 0,
"size": 232,
"type": "text/html",
},
},
"headers": Headers {
"map": Object {
"connection": "keep-alive",
"content-length": "232",
"content-type": "text/html",
"date": "Thu, 03 Oct 2019 18:15:10 GMT",
"server": "gunicorn/19.9.0",
"via": "1.1 vegur",
},
},
"ok": false,
"status": 404,
"statusText": undefined,
"type": "default",
"url": "https://neighbor-hood.herokuapp.com/user/create",
}
Object {
"isError": true,
"isLoading": false,
"isSuccess": false,
}
I don't think my API is working and when I try it on postman I get a 404 message.
This explains that you have some backend error because even when you are trying from postman you get error of 404 which is error from backend.
Trying to fetch data from API using async/await, but facing the above error after session expiration, how to handle that error and show user session expired or any other helpful error?
export const walletAddCardRequest = async (dispatch, token, payload, url) => {
try {
persist.store.dispatch(setLoader(true));
const headers = {Authorization: token}
const response = await api(url, "POST", payload, headers);
console.log("wallet add card ", response);
persist.store.dispatch(setLoader(false));
if (response.status === 200) {
const user = await response.json();
if (user) {
persist.store.dispatch(setLoader(false));
Alert.alert(
"",
"Your card added successfully."
);
navigateTo("wallet");
} else {
throw new Error("Error. Please try again");
}
} else {}
} catch (e) {
persist.store.dispatch(setLoader(false));
Alert.alert(e.message);
console.log("console:",e);
dispatch({
type: AUTH_ERROR
});
}
}