Correct Placement Of Try/catch Block When Using Non-immediate Async/await
I've been using async/await for 6 months and been loving the syntactic sugar. I typically use it the traditional way:
try {
await doSomethingAsync()
}
catch (e) {}
Recently I've started experimenting with not awaiting immediately so that i run some extra code in this context before waiting for the async data, like:
let p = doSometiongAsync()
... do more stuff
await p;
or:
let p1 = doJob1();
let p2 = doJob2();
... do more synchronous stuff ...
await p1;
await p2;
The question is, where is the correct placement of the try/catch blocks to make sure errors (either synchronous or asynchronous) within the calls are caught properly. Is it around the initial function call:
try {
let p = doSomethingAsync()
} catch(errors) {}
... do stuff ...
await p
or try block around the await... or two different try blocks, one for each?
try {
let p = doSomethingAsync()
} catch(errors) {}
... do stuff
try {
await p;
} catch (evenmoreerrors) {}
thx!
Answer
It depends on what doSomethingAsync
is: An async
function, or a non-async
function that returns a promise.
If it's an async
function
...you just need the try
/catch
around the await
; an async
function never throws synchronously (even if the exception is thrown by the initial synchronous portion of it).
Example:
async function foo() {
// Note this is in the synchronous portion
console.log("synchronous part of foo");
if (true) {
throw new Error();
}
return new Promise(resolve => {
resolve();
});
}
(async () => {
const p = foo(); // No uncaught error
try {
await p;
} catch (e) {
console.log("Caught the error");
}
})().catch(e => {
console.log("Failed to catch it!");
});
If it's a non-async
function that returns a promise
...then depending on the function, you may need try
/catch
in both places, or not, depending on how it's written. If it may throw in its synchronous code, you need try
/catch
around that. And you need try
/catch
around the await
in case of promise rejection.
Example of not handling the synchronous part:
function foo() {
// Note this is in the synchronous portion
console.log("synchronous part of foo");
if (true) {
throw new Error();
}
return new Promise(resolve => {
resolve();
});
}
(async () => {
const p = foo(); // No uncaught error
try {
await p;
} catch (e) {
console.log("Caught the error");
}
})().catch(e => {
console.log("Failed to catch it!");
});
Example of failing to catch the promise rejection:
function foo() {
// Note this is in the synchronous portion
console.log("synchronous part of foo");
return new Promise((resolve, reject) => {
reject();
});
}
(async () => {
try {
const p = foo();
} catch (e) {
console.log("Caught the error");
}
await p;
})().catch(e => {
console.log("Failed to catch it!");
});
Related Questions
- → How to update data attribute on Ajax complete
- → October CMS - Radio Button Ajax Click Twice in a Row Causes Content to disappear
- → Octobercms Component Unique id (Twig & Javascript)
- → Passing a JS var from AJAX response to Twig
- → Laravel {!! Form::open() !!} doesn't work within AngularJS
- → DropzoneJS & Laravel - Output form validation errors
- → Import statement and Babel
- → Uncaught TypeError: Cannot read property '__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
- → React-router: Passing props to children
- → ListView.DataSource looping data for React Native
- → Can't test submit handler in React component
- → React + Flux - How to avoid global variable
- → Webpack, React & Babel, not rendering DOM