Reputation: 122
So basically I am running some code that queries a graphql api, and checks whether the data field inside is null (meaning there are no hits for the query), like so:
// check if the items have available data.
// if not, throw an error message saying which ones did not have data.
const testIfDataInDB = await Promise.all(objIDs.map(objID => {
return fetch("/api/graphql", {
method: "POST",
headers: headers,
body: JSON.stringify({
query: "query get_object_with_obj_number($objectNumber: String!) { constructionDetail(objectNumber: $objectNumber) { objectNumber } }",
variables: {
objectNumber: objID
}
}
)
}).then(async (res) => {
return {
responseData: await res.json(),
objID: objID
}
}
)
}));
const itemsDataNotFound = testIfDataInDB.filter(o =>
o.responseData?.data?.constructionDetail === null);
let errString = "";
if (itemsDataNotFound.length > 0) {
itemsDataNotFound.forEach(obj => {
errString = errString + `${obj.objID}, `;
});
errString = errString.slice(0, errString.length - 2);
console.log(errString);
throw new Error(errString);
}
// ... do some object transformations ...
// proceed to post some items into another db using fetch.
const response = await Promise.all(objectsArr.map((obj, index) => {
const body = JSON.stringify(obj);
if (update && index === 0) {
const fetchUrl = `${baseFetchUrl}/${parentItemMetadata._id}`
return fetch(
fetchUrl, {
method: "PUT",
headers: headers,
body: body
}
).then(res => res.json())
}
return fetch(
baseFetchUrl, {
method: "POST",
headers: headers,
body: body
}
).then(res => res.json())
}))
console.log(response);
return response;
}
and the way im calling this code inside my react component:
//defined in parent
const saveMultipleItems = async (
objIDs: string[],
update: boolean
) => {
const parentItemMetaData: TypeLabelItemMetaData = {
createdBy: currentItem?.createdBy || "",
createdAt: currentItem?.createdAt || "",
updatedBy: currentItem?.updatedBy || "",
updatedAt: currentItem?.updatedAt || "",
_id: currentItem?._id || "",
collection: currentItem?.collection || ""
}
try {
saveMultiple(
objIDs,
labelType,
values as TypeLabelState,
parentItemMetaData,
user,
update
)
} catch (e) {
console.warn(e.message);
} finally {
fetchItems();
}
// called in child component
onSubmit={(e) => {
e.preventDefault();
console.log("submitting a series")
try {
const pNumbersArray = generateArray(fromObjNumber, toObjNumber);
saveSeriesFn(pNumbersArray, editMode);
} catch (e) {
console.log("catched error")
alert("Saving series failed with message " + e.message);
}
}
}
My plan was to throw an error, and react to this error somewhere where I can show an alert saying that some items are not available to be saved, and abort the saving operation. I kn I know this may not be the cleanest way to do this (I am also very grateful for sugestions). The problem I am having right now, is that the app crashes with the following:
Unhandled Rejection (Error): P18100405117, P18100405118, P18100405119
saveMultiple
src/app/src/api/savemultiple.ts:70
67 | });
68 | errString = errString.slice(0, errString.length - 2);
69 | console.log(errString);
70 | throw new Error(errString);
| ^ 71 | }
72 |
73 | const objectsArr: SaveTemplateObjType[] = objIDs.map((objID, index) => {
I thought I was not inside a Promise at the moment I threw this Error?
Upvotes: 0
Views: 59
Reputation: 1634
Async/Await is a synthetic sugar for Promises
Your code states: const saveMultiple = async(...
An Async function will always return a Promise. (see refs below)
Your try/catch doesnt take affect in:
try {
saveMultiple(
objIDs,
labelType,
values as TypeLabelState,
parentItemMetaData,
user,
update
)
} catch (e) {
console.warn(e.message);
} finally {
fetchItems();
}
because saveMultiple
is async. you need to use:
saveMultiple(
objIDs,
labelType,
values as TypeLabelState,
parentItemMetaData,
user,
update
).catch((e) => {
console.warn(e.message);
}).finally(() => {
fetchItems();
})
From MDN:
Upvotes: 1