Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule proposal: Prefer setting process.exitCode to calling process.exit() #1530

Open
fregante opened this issue Sep 18, 2021 · 7 comments
Open

Comments

@fregante
Copy link
Collaborator

fregante commented Sep 18, 2021

Extends:

Context:

The reason this is problematic is because writes to process.stdout in Node.js are sometimes asynchronous and may occur over multiple ticks of the Node.js event loop. Calling process.exit(), however, forces the process to exit before those additional writes to stdout can be performed.

I'm not sure if this is applicable to every situation, but perhaps process.exit(1) should be the exception, not the rule.

Fail

process.exit(1);

Pass

process.exit(); // No code, the intent is a bit more clear
process.exitcode = 1;
@fregante fregante changed the title Rule proposal: Rule proposal: prefer setting exitcode Sep 18, 2021
@fregante fregante changed the title Rule proposal: prefer setting exitcode Rule proposal: prefer setting exitcode to calling process.exit Sep 18, 2021
@sindresorhus sindresorhus changed the title Rule proposal: prefer setting exitcode to calling process.exit Rule proposal: Prefer setting process.exitCode to calling process.exit() Sep 25, 2021
@sindresorhus
Copy link
Owner

One problem with this is that you cannot use return at the top-level. This causes problems with early-return logic in CLIs:

if (cli.input.length === 0) {
	console.log('Please specify a unicorn');
	process.exit(1);
}

init();

If we use process.exitCode here, we have to refactor it into an if-else, which makes it slightly less readable.

@papb

This comment was marked as resolved.

@fregante
Copy link
Collaborator Author

fregante commented Dec 31, 2023

if (cli.input.length === 0) {
	console.log('Please specify a unicorn');
	process.exit(1);
}

Wouldn't it be "better" to just throw? I know it's ugly, but at least it's guaranteed. The note in docs still applies:

Calling process.exit() will force the process to exit as quickly as possible even if there are still asynchronous operations pending that have not yet completed fully, including I/O operations to process.stdout and process.stderr.

presentable-error actually suggests the pattern that this rule warns against. I wrote code that works for both in sindresorhus/del-cli#34 (comment)

That code can use error.isPresentable instead of checking for the ENV, if preferred, but the format stands.

@sindresorhus
Copy link
Owner

Alternatively:

(() => {
	if (cli.input.length === 0) {
		console.log('Please specify a unicorn');
		process.exitCode = 1;
		return;
	}

	// ...
})();

// or

if (cli.input.length === 0) {
	console.log('Please specify a unicorn');
	process.exitCode = 1;
} else {
	// ...
}

So annoying that we cannot use return top-level though...

@sindresorhus
Copy link
Owner

Sidenote, maybe meow should have a printAndExit() method that prints, flushes, and then exits? And maybe even an option to require input to not be empty and accept an error message if not.

@fregante
Copy link
Collaborator Author

fregante commented Jan 1, 2024

To be honest I'd rather just always wrap my logic in an init function in any case, even if that "prefer top level await" rule warns against it. I very rarely have any logic at the top level anyway, unless trivial.

So in this case I'd use

function init() {

}

init();

instead of the IIFE, so it looks decent and pretty standard.

@sindresorhus
Copy link
Owner

The IIFE was not the point of my comment though. I could have used a "main" function there too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants