This content originally appeared on Jake Archibald's blog and was authored by Jake Archibald's blog
In JavaScript functions, which return
wins?
function test() {
return 'one';
return 'two';
return 'three';
}
You might say, "well it's the first one", but I'm going to try and convince you it's the last one.
Don't worry, the function above definitely returns 'one'
, but in this case the first return statement prevents the others from executing. The last return is return 'one'
, and that's the one that wins. Sure, it's also the first return, but I'm still right. [folds arms and looks smug]
I know what you're thinking, you're thinking "shut up jake", but bear with me…
Finally
finally
is a thing:
function finallyTest() {
try {
console.log('one');
return 'three';
} catch (err) {
console.log('error');
} finally {
console.log('two');
}
}
console.log(finallyTest());
console.log('four');
The above logs 'one'
, 'two'
, 'three'
, 'four'
. The finally
block always runs after a try
/catch
, even if the try
or catch
return.
I hadn't used finally
much in JavaScript, but I find myself using it quite a bit in async functions, in patterns like this:
async function someAsyncThing() {
startSpinner();
try {
await asyncWork();
} catch (err) {
if (err.name === 'AbortError') return;
showErrorUI();
} finally {
stopSpinner();
}
}
Anyway, the exciting thing about finally
is it gives us the opportunity to return many times from a single function call:
function manyHappyReturns() {
try {
return 'one';
} finally {
try {
return 'two';
} finally {
return 'three';
}
}
}
…and the result of calling manyHappyReturns()
is 'three'
. The last return always wins. The same happens in Java and Python too. Thanks to Daniel Ehrenberg for making me aware of this little quirk!
As a side-effect, returning from finally
clears a thrown error:
function catchThis() {
try {
throw Error('boom');
} finally {
return 'phew';
}
}
The result of calling catchThis()
is 'phew'
.
What's the practical application of this?
There isn't one. Thanks for reading! Please never quiz folks about this in a job interview.
Bonus: Promises
Async functions behave the same as above, except they return a promise. However, promise objects behave differently:
const promise = Promise.resolve('one').finally(() => 'two');
Here, promise
fulfils with 'one'
. This is probably because promise reactions are callbacks, and the caller of a callback (which is the promise in this case) has no way of telling the difference between a function that runs return undefined
and one that doesn't run return
at all. Since it can't mimic the finally
edge case above, it just ignores it.
Although, promise.finally
does impact when the promise resolves:
const wait = (ms) => new Promise((r) => setTimeout(() => r(), ms));
const promise = Promise.resolve('one').finally(async () => {
await wait(2000);
return 'two';
});
In this case promise
still fulfils with 'one'
, but it takes two seconds to do so.
This content originally appeared on Jake Archibald's blog and was authored by Jake Archibald's blog
Jake Archibald's blog | Sciencx (2021-06-24T01:00:00+00:00) In JS functions, the last return wins. Retrieved from https://www.scien.cx/2021/06/24/in-js-functions-the-last-return-wins/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.