I have this repro: https://codesandbox.io/s/jolly-bogdan-k6ii4?file=/src/index.ts
code:
const wait = (timeoutMs: number) => {
let timeoutHandle: number | undefined;
const promise = new Promise((_resolve, reject) => {
timeoutHandle = setTimeout(() => {
reject(`wait timed out after ${timeoutMs} ms`);
}, timeoutMs);
});
return {
promise,
cancel: (): void => clearTimeout(timeoutHandle)
};
};
const waitBy = (timeoutMs: number) => {
const res = wait(timeoutMs);
return res;
};
const main = async () => {
try {
const { promise, cancel } = waitBy(3000);
} catch (error) {
console.log("failed on timeout");
}
// try {
// await promise;
// } catch (error) {
// console.log("timed out");
// }
};
main();
When this is ran in Node.js, the reject will throw after 3s, and blow up the whole process with an "unhandledRejection Error" - where can one catch this error to avoid an unhandledRejection Error, but allow it to propagate up to the catch inside the main function?
The problem is that you're not waiting for the promise to resolve before moving forward and the error is thrown then outside of the try block.
const main = async () => {
try {
const { promise, cancel } = waitBy(3000);
await promise // new code
} catch (error) {
console.log("failed on timeout");
}
// try {
// await promise;
// } catch (error) {
// console.log("timed out");
// }
};
Related
I have simple route:
fastify.post('/subscribe', {
schema: subscribeSchema,
handler: async (req, reply) => {
try {
const events = req.body.events;
const allEventsProcessingData = await Promise.all(events.map(async (ev) => {
return {
event: ev,
feedEventsData: await getFeedEventData(ev),
feedMainMarketsData: await getFeedEventMainMarketsData(ev),
}
}));
// process HTML by events data
// allEventsProcessingData
const compiledHTML = '';
return reply.send(compiledHTML);
} catch (e) {
console.log('e', e);
return reply.send(HTTP_RESPONSES.FAIL);
}
}
});
When error happens, the response does not send, why is it? And how to send it? Tried this https://github.com/fastify/fastify/issues/1864#issuecomment-534233381, but it did not work.
I am having problems do handle UnhandledPromiseRejectionWarning in a function that call other functions making axios request.
const getCode = async () => {
const code = await baseURL.get('/gcs/login/k?codigoCanal=4')
return code
}
const posLogin = async (code) => {
const poslogin = await baseURL.get(`/resource/autenticar/${code}`)
return poslogin
}
const login = async () => {
try {
const code = await getCode();
const finishedLogin = async posLogin(code)
} catch (error) {
handleLoginError(error)
}
}
const handleLoginError = (error) => {
if (error.response.status === 400) {
throw new Error(`Bad Request; ${error.response.statusText}`)
}
if (error.response.status === 401) {
throw new Error(`Wrong credentials; ${error.response.statusText}`)
}
throw new Error('Unknown Error')
}
login()
Executing this code returns me UnhandledPromiseRejectionWarning, but I realized that if I put a try catch inside the catch of login functionn, this warning disappears
} catch (error) {
try {
handleLoginError(error)
} catch (err) {
console.log('Ooppss', err)
}
When I do this my code enter in the nested catch and the "err" value is the value of the handleLoginError(error)
How can I do the same without executing a try catch inside the catch?
It seems you need to call login as follows:
try {
await login();
}
catch(err) {
// handle here the error
}
I am trying to re-create bluebird's promise.try function, is this essentially the same?
function promiseTry(callback) {
let error;
let value;
try {
value = callback();
} catch (e) {
error = e;
}
return new Promise((resolve, reject) => {
if (error) {
reject(error);
throw error;
}
resolve(value);
});
}
const x = promiseTry(() => {
throw new Error('hi');
});
How can I simply implement bluebird's Promise.try with a native node Promise?
This should be equivalent:
function promiseTry(callback) {
return new Promise((resolve, reject) => {
try {
resolve(callback())
} catch(e) {
reject(e);
}
});
}
const x = promiseTry(() => {
throw new Error('hi');
});
x.then(() => console.log("Promise resolved")).catch(err => console.log("Promise rejected:", err.message));
If you can use async/await, async functions have this behavior implicitly. Any synchronous exceptions thrown in an async function are converted into a promise rejection.
I am processing multiple records using async/await and for parallel using Promise.all see my sample code below
let results = [100,200]
let promises = results.map(async record => {
try {
return await processingRecords(record);
} catch (err) {
}
});
await Promise.all(promises);
async function processingRecords(item) {
switch (item['#type']) {
case 'case1':
await Request1(item)
await Request2(item)
break
case 'case2':
await Request3(item)
}
}
But the problem is if Request1 is getting any error I can't catch error from Request2 call how to handle error from both calls
You can to do a few things here to keep the calls going. Catching errors around the await statements and returning the combined result of Request1 and Request2 will work:
For example:
async function processingRecords(item) {
switch (item['#type']) {
case 'case1':
let combinedResult = {};
try {
combinedResult.Request1Result = await Request1(item);
} catch (err) {
combinedResult.Request1Error = err;
}
try {
combinedResult.Request2Result = await Request2(item);
} catch (err) {
combinedResult.Request2Error = err;
}
// Keep the promise chain intact.;
return combinedResult;
case 'case2':
return await Request3(item);
}
}
let promises = results.map(async record => {
try {
return await processingRecords(record);
} catch (err) {
// Keep the promise chain intact by throwing err here.
throw err;
}
});
let overallResult = await Promise.all(promises);
console.log(overallResult);
I have this code:
async function getURL() {
try {
await fetch("http://www.blah.com");
return 0;
} catch (err) {
return err;
}
}
getURL().then( result => {
if (result === 0) console.log("success");
else console.log(result);
});
The fetch will fail and the error is logged to the console. How do I rework the code so it uses async and try/catch everywhere? That is, I'm looking to avoid doing getURL().then for the sake of consistency.
EDIT:
For those downvoting me, await getURL() won't work as it's invalid syntax.
EDIT2:
Tried this but it didn't catch the error:
async function getURL() {
return await fetch("http://www.blah.com");
}
let result = async function() {return await getURL();}
try {
result();
} catch (e) {
console.log(e);
}
You can wrap your whole code inside an instantly executed async function like this:
// service.js
async function getURL() {
return await fetch("http://www.blah.com");
}
// your.module.js
(async function() {
// do things...
try {
let result = await getURL();
} catch (e) {
console.log(e);
}
// do things...
res.send({});
});
Every time you need to catch an error from promise, either using new Promise, async-await or generator you need to use .then() or you can do something like this another async-await.
async function getURL() {
try {
await fetch("http://www.blah.com");
return 0; // EDIT: just returning value which is success
} catch (err) {
return err; // EDIT: returning value not rejecting a promise
}
}
async function main () {
try {
let result = await getURL();
if (result === 0) console.log("success");
console.log(result); // EDIT: error will be print.
}
catch (err) { // EDIT: getURL() never rejects so always success.
console.log(err);
}
});
main();
This situation doesn't really occurs as while our main function in server-side or client-side are async and handling this for us.
Like using express:
app.post('/api', async (req, res) => {
try {
let result = await getURL();
res.send(async);
}
catch(err) {
res.send(err);
}
});
EDIT: asyn-await doesn't reject or resolve a call, just return a value. thus must be used carefully.
function fetch(url) {
return new Promise( (resolve, reject) => {
let x = Math.floor(Math.random() * Math.floor(9) + 1);
// 50-50 resolve or reject
if(x%2===0) return resolve(false); //resolve with `false` statement
reject(true); // reject with `true` still a reject
});
}
async function getURL() {
try {
await fetch("http://www.blah.com");
return 0; // if fetch resolve
} catch (err) { //only if fetch reject
return err;
}
}
async function main () {
try {
let result = getURL();
if (result === 0) console.log("success"); //getURL never reject any call
console.log(result);
}
catch (err) { // getURL doesnt reject
console.log(err);
}
};
main();
I realize now async functions always return a promise. Even if you throw an error it still gets wrapped up into a promise. Therefore using try/catch won't help. This is how I ended up writing the code:
async function getURL() {
return await fetch("http://fake");
}
getURL().then( () => console.log("success")).catch( (e) => console.log(e));