Coder Social home page Coder Social logo

make-promises-safe's Introduction

make-promises-safe   Build Status

A Happy Note

If you are using Node.js version 15+, the correct promise behaviour is already implemented and Node.js will safely behave on unhandled rejections similarly to its uncaught exception behaviour. If you are only using Node.js v15+ there is no need to use this module.

If you need to support older versions of Node.js - it is a good idea to use this module to ensure future compatibility with modern Node.js versions where the safe behaviour is the default one.

What this is

A node.js module to make the use of promises safe. It implements the deprecation DEP0018 of Node.js in versions 6+. Using Promises without this module might cause file descriptor and memory leaks.

It is important that this module is only used in top-level program code, not in reusable modules!

The Problem

Node.js crashes if there is an uncaught exception, while it does not crash if there is an 'unhandledRejection', i.e. a Promise without a .catch() handler.

If you are using promises, you should attach a .catch() handler synchronously.

As an example, the following server will leak a file descriptor because of a missing .catch()  handler:

const http = require('http')
const server = http.createServer(handle)

server.listen(3000)

function handle (req, res) {
  doStuff()
    .then((body) => {
      res.end(body)
    })
}

function doStuff () {
  if (Math.random() < 0.5) {
    return Promise.reject(new Error('kaboom'))
  }

  return Promise.resolve('hello world')
}

The Solution

make-promises-safe installs an process.on('unhandledRejection') handler that prints the stacktrace and exits the process with an exit code of 1, just like any uncaught exception.

Install

npm install make-promises-safe --save

Usage

'use strict'

require('make-promises-safe') // installs an 'unhandledRejection' handler
const http = require('http')
const server = http.createServer(handle)

server.listen(3000)

function handle (req, res) {
  doStuff()
    .then((body) => {
      res.end(body)
    })
}

function doStuff () {
  if (Math.random() < 0.5) {
    return Promise.reject(new Error('kaboom'))
  }

  return Promise.resolve('hello world')
}

as a preloader

You can add this behavior to any Node.js application by using it as a preloader:

node -r make-promises-safe server.js

with core dumps

You can also create a core dump when an unhandled rejection occurs:

require('make-promises-safe').abort = true

With custom logging

You can add a custom logger to log errors in your own format. To do this override the logError property with a function that takes a single Error parameter. This defaults to console.error.

const makePromisesSafe = require('make-promises-safe');
makePromisesSafe.logError = function(err) {
  // log the err object
}

License

MIT

make-promises-safe's People

Contributors

a-a-github-a-a avatar benjamingr avatar bridgear avatar colestrode avatar lependu avatar mcollina avatar nigelhanlon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

make-promises-safe's Issues

When will the deprecation be enforced in Core not User-land?

@mcollina Nice work on this, thanks!

Sorry to make an issue just to ask a question, let me know if i should have asked some other way.

Anyway, I was wondering when this deprecation will be enforced? i.e. when will uncaught promise rejections actually kill the process?

Nightly builds don't seem to be, even for v9.

nvm use 9 && node -e 'Promise.reject()'
Now using node v9.0.0-nightly20170620d2913384aa (npm v5.0.3)
(node:70293) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): undefined
(node:70293) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Question about node v15 usage

Just so I understand correctly... since the the default mode for unhandledRejection is changed to throw, is it correct to say that this package is now no longer needed for newer versions?

make-promises-debuggable

Suggestion for a sequel module: make-promises-debuggable

Might not be possible, but making a process crash when there's a syntax error
in a promise that already has a catch handler would be helpful for development experience

Always attach listener

Currently the listener is only attached if there's no other listener. I personally believe it should always be attached no matter if other listeners already exist or not as the user actively opted in.

It would also be good to add a warning in the docs that this library should not be used by any "regular" module but only by the users that write the used application.

Question: Why the Warning about not using this in Reusable Modules?

The README.md for this project currently contains the following warning

It is important that this module is only used in top-level program code, not in reusable modules!

but does not (or does it?!) really explain why it's important to only use this module in top level program code.

Is this simply a best practice warning against surprising users by changing the behavior of their un-handled promise rejections via a third party module? Or are there other, subtle problems with defining a process level unhandledRejection handler via reusable module code?

Replace process.exit(1) with process.exitCode

According to Node.js recommendation:

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.
In most situations, it is not actually necessary to call process.exit() explicitly. The Node.js process will exit on its own if there is no additional work pending in the event loop. The process.exitCode property can be set to tell the process which exit code to use when the process exits gracefully..

if you think this is necessary I can create a PR.

Critical Promise.race() fail

Any usage of Promise.race() with more than 1 resolving promise triggers an exit!!

require('make-promises-safe');

Promise.race([Promise.resolve('a'), Promise.resolve('b')]);

setImmediate(() => console.log('done'));

Result:

resolve Promise { 'a' } b

Version: 3.0.0
Node: v10.13.0

Add a "files" (whitelist) field to package.json ?

Hi,

I'm working on a security tool and i'v discovered that some files has been published in the tarball:

  • example.js
  • test.js
  • .travis.yml

So because you'r using http in example.js my tool put a flag (the little planet). If there is no reason to publish these files, can you consider removing them for the next release ?

(to be added to the package.json)

{
  "files": ["make-promises-safe.js"]
}

Thanks for your time and work.

Best Regards,
Thomas

exit code

is there possible scenarios where the exit code wouldn't be 1
(depending on the nature of the error in the rejection?)

If so, how do we handle this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.