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
finally
block runs regardless of whether areturn
,throw
, or an exception occurs intry
orcatch
. - If
finally
has areturn
, it overrides any return value or thrown error fromtry
orcatch
.
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
await
is 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
finally
throws an error or returns a rejected promise, it overrides any previousreturn
orthrow
.
async function test() {
try {
return "from try";
} finally {
throw new Error("from finally");
}
}
test().catch(console.error);
// Logs: Error: from finally
- Forgetting
await
when returning a promise fromtry
can cause unintended behavior iffinally
modifies 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
finally
block contains anawait
but you forgetawait
in thetry
block’s return, thefinally
block 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
await
promises intry
if you intend to wait for them. - Avoid returning values from
finally
unless explicitly needed. - Be aware that errors thrown in
finally
override anything fromtry
orcatch
. - Use
finally
for cleanup logic, not for altering return values or error states unless intentional.