Node.js Promise reject use case survey

Image for post
Image for post

Today, Node.js Project, an impact project of the OpenJS Foundation, handles unhandled rejections by emitting a deprecation warning to stderr. The warning shows the stack where the rejection happened, and states that in future Node.js versions unhandled rejections will result in Node.js exiting with non-zero status code. We intend to remove the deprecation warning, replacing it with a stable behavior which might be different from the one described on the deprecation warning. We’re running a survey to better understand how Node.js users are using Promises and how they are dealing with unhandled rejections today, so we can make an informed decision on how to move forward.

What is a Promise rejection?

Adding the async keyword to a function will turn any exceptions thrown inside that function (or any throw propagated from other functions called within it) into a rejection. The same happens when refactoring callback based code that throws into async functions / Promises. Below is an example of a callback based code refactored to Promises where exceptions become rejections:

What is an unhandled rejection?

Promises are designed so that attaching handlers or awaiting can be done at any point in time, from when the Promise was created (possibly while it’s still pending), to right before the program finishes execution.

A rejection is considered unhandled from the point it happens until the point where a handler is attached to the Promise or the Promise is awaited within a catch {} block. Below are a few examples of handled and unhandled rejections.

As we can see in the examples, an unhandled rejection might be handled in the future, like example 5, but it might also stay unhandled forever (like example 4).

Certain unhandled rejections may in rare cases leave your application in a non-deterministic and unsafe state, whether it’s internal application state (including memory leaks), external resources used by your application (say, file handles or database connections), or external state (say, consistency of data in a database). As an example, the following server is not sending a response back to the client, causing a socket leak and a possible Denial of Service attack:

Mitigating the issue

The process will crash, but that might be preferrable to leaking resources in this case. In other cases, the listener might attempt to gracefully recover or to gracefully shut down by first responding to any requests still in progress, and only crash if it can’t respond to pending requests.

Using the listeners requires changing the application code, and the behavior can be overridden by any dependency. To circumvent those limitations, a new flag (--unhandled-rejection=[mode]) was added to Node.js. This flag supports five different modes:

  • strict: raise an uncaught exception similar to throw new Error() that is not caught. unhandledRejection listeners do not prevent raising the exception
  • throw: raise an uncaught exception similar to throw new Error() that is not caught. unhandledRejection listeners take precedence and prevent raising the exception
  • warn: outputs a warning as soon as possible. Continues running after the warning is emitted. If the process exits and no status code was set, the process exits with a success code. This is similar to what browser consoles do
  • warn-with-error-code: outputs a warning as soon as possible. Continues running after the warning is emitted. If the process exits and no status code was set, the process exits with an error code
  • none: do nothing

For all the modes, the action (raise an exception output a warning) will happen on nextTick. strict mode circumvents the problem stated above since it prevents dependencies from overriding the unhandleRejection listener. warn is similar to the current behavior but without a deprecation warning.

Either the listener and flag can be used to mitigate issues with unhandled rejections.

Defining a default for the project

To help us decide on a default, please complete our survey: https://www.surveymonkey.com/r/FTJM7YD

Node.js is a collaborative open source project dedicated to building and supporting the Node.js platform. https://nodejs.org/en/

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store