3 ms·
While this is 100% correct, if the main function has returned then the process was going to end anyway (assuming there isn't additional code after the call to m
by robert_tweed 7y ago
While this is 100% correct, if the main function has returned then the process was going to end anyway (assuming there isn't additional code after the call to main). If there's a main loop, then the catch needs to be inside that loop, not outside of main.
The only difference it will make here is to suppress the default stack trace[1] and errorlevel returned to the shell. If you are writing in this kind of "scripting" style, you probably don't want to suppress errorlevels, so leaving out the catch is not only simpler, it is safer.
[1] You may get a stack trace with an Error object, but not the default one from the Node process.
- olalonde 7y ago> While this is 100% correct, if the main function has returned then the process was going to end anyway (assuming there isn't additional code after the call to main). That's not necessarily the case (or maybe poorly worded), e.g.: async function main() { // code setInterval(() => console.log('hey'), 1000) } main() In real life, it would probably be a HTTP server holding up the process. It's true that you likely want to crash hard if you have unhandled error during server initialization but I would still catch the error because Node.js will otherwise print a bunch of ugly "UnhandledPromiseRejectionWarning" messages. E.g.: main().catch(err => { console.error(err); process.exit(1); }); With top level async landing in v8, I guess Node.js will eventually stop printing those warning messages.
- robert_tweed 7y agoYou raise an interesting point. If you are doing anything non-trivial, you should definitely be using a main loop and catching errors inside that loop. You really don't want to rely on the default behaviour of orphaned timers, because that can get interesting. I did a quick test just to see how bad things might get if you were to rely on orphaned timers like this. The important thing to keep in mind is that each of those timers is effectively its own thread, which can throw errors and terminate itself. But if those are orphaned outside of a runloop that can handle those errors, they will not be caught by the catch outside of main (which only catches errors thrown in the "main thread"). Rather, they become top-level, uncaught exceptions, which also terminate the process. Here's an example illustrating what happens: async function main() { setTimeout( () => console.log( 'Hello' ), 3000 ); setTimeout( function() { throw new Error('error 1'); }, 1000 ); setTimeout( function() { throw new Error('error 2'); }, 2000 ); throw new Error('oops'); } main().catch( x => console.error( x ) ); The result here is that `oops` is displayed (the caught error from the "main thread") and then `error 1` is displayed, but the process is then immediately terminated. Neither `error 2` nor `Hello` are displayed. Note that I use the term "thread" loosely, in the "green thread" sense. Hopefully the meaning is clear.