In JavaScript, the interaction between return, await, and finally can cause subtle issues that developers should be aware of. Here are some key gotchas:
- The
finallyblock runs regardless of whether areturn,throw, or an exception occurs intryorcatch. - If
finallyhas areturn, it overrides any return value or thrown error fromtryorcatch.
function test() {
try {
return "from try";
} catch (e) {
return "from catch";
} finally {
return "from finally"; // Overrides the previous return
}
}
console.log(test()); // "from finally"- If
awaitis used insidefinally, the function execution is paused, and the result is returned only after the awaited promise resolves.
async function test() {
try {
return "from try";
} finally {
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("finally completed");
}
}
test().then(console.log);
// Logs "finally completed" after 1 second
// Then logs "from try"- If
finallythrows an error or returns a rejected promise, it overrides any previousreturnorthrow.
async function test() {
try {
return "from try";
} finally {
throw new Error("from finally");
}
}
test().catch(console.error);
// Logs: Error: from finally- Forgetting
awaitwhen returning a promise fromtrycan cause unintended behavior iffinallymodifies the control flow.
async function test() {
try {
return Promise.resolve("from try"); // Missing await!
} finally {
console.log("finally executed");
}
}
test().then(console.log);
// Logs: "finally executed"
// Logs: "from try"- If the
finallyblock contains anawaitbut you forgetawaitin thetryblock’s return, thefinallyblock may delay the completion of the function.
async function test() {
try {
return Promise.resolve("from try"); // Not awaited
} finally {
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log("finally done");
}
}
test().then(console.log);
// Logs: "finally done" after 1 second
// Logs: "from try"- Always
awaitpromises intryif you intend to wait for them. - Avoid returning values from
finallyunless explicitly needed. - Be aware that errors thrown in
finallyoverride anything fromtryorcatch. - Use
finallyfor cleanup logic, not for altering return values or error states unless intentional.