Last active
October 6, 2023 08:31
-
-
Save benjamingr/0237932cee84712951a2 to your computer and use it in GitHub Desktop.
Revisions
-
benjamingr revised this gist
Feb 8, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -30,7 +30,7 @@ process.on('unhandledRejection', function(reason, p){ }); ``` ###Event 'rejectionHandled': Emitted whenever a possibly unhandled rejection was mistakenly identified and was eventually handled. For example if the promise library made a mistake considering `p` in the following case unhandled: -
benjamingr revised this gist
Feb 8, 2015 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -16,21 +16,21 @@ This document attempts to offer a standard way for promise libraries and potenti In order to handle rejections the following new events will be fired on `process`: ###Event 'unhandledRejection': Emitted whenever a possibly unhandled rejection is detected. This event is emitted with the following arguments: - `reason` the rejection reason of the promise susprected in having an unhandled rejection - `p` the promise suspected in having an unhandled rejection itself. ```js process.on('unhandledRejection', function(reason, p){ console.log("Possibly Unhandled Rejection at: Promise ", p, " reason: ", reason); // application specific logging here }); ``` ###Event 'unhandledRejectionHandled': Emitted whenever a possibly unhandled rejection was mistakenly identified and was eventually handled. For example if the promise library made a mistake considering `p` in the following case unhandled: -
benjamingr revised this gist
Jan 27, 2015 . 1 changed file with 14 additions and 14 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -44,6 +44,20 @@ This event is emitted with the following arguments: This event is useful in order to recover from detection mistakes. While in my experience this rarely happens in practice this additional hook helps in such cases. ##Backwards incompatible changes None that I am aware of. No one is currently firing events by these names in NodeJS code in GitHub. ##In other languages Promises as an abstraction are indeed not unique to JavaScript - let's explore what other languages do. - in C# 4.0 and .NET in general - such a hook exists for Task with an unterminated error handler will crash your application unless you add a `TaskScheduler.UnobservedTaskException` event handler. In 4.5 you can handle errors yourself (like `.catch`). - In Scala it used to silent fail (lots of surprised answers in SO - e.g. http://stackoverflow.com/questions/24453080/) but that upset people https://groups.google.com/forum/#!searchin/scala-user/The$20silence$20of$20failed$20futures/scala-user/1X2QISf3604/2dw0XhMh0RUJ , they now intend to support that case. - Dart futures already do this forwarding rejections to the global error handler. So overall it seems like other programming environments support a unhandled rejection hander. Note that JavaScript is pretty special in that it is the only case I know of where a lot of different implementations of this abstract concept exist. ##Statistics @@ -93,20 +107,6 @@ Here are libraries and projects using `onPossiblyUnhandledRejection` in their co - https://github.com/martin-liu/m-sails/blob/f02f33a60c424517168b365c0c61da4ad85b8ba6/api/coffee/services/Promise.coffee (0 stars, personal project) - https://github.com/danprince/cyvasse (Game, 0 stars, undefined passed to get Q like behavior, lots (100) like this using bundler.js) ##Future work Add a similar solution for promise libraries in browsers, possibly the [WhatWG proposal](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0024.html). -
benjamingr revised this gist
Jan 27, 2015 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -47,11 +47,11 @@ This event is useful in order to recover from detection mistakes. While in my ex ##Statistics These are usage statistics about events current libraries already fire. These usage examples were collected from public GitHub projects using bluebird promises offering (non-global) hooks. First a summary of bluebird's `onPossiblyUnhandledRejection` from GitHub. Large (>1000 stars) libraries typically don't change onPossiblyUnhandledRejection, the largest ORMS: Sequelize, Waterline and Bookshelf do not hook on it however users of those libraries sometimes do. It also very common for people to override it in test code. Here are libraries and projects using `onPossiblyUnhandledRejection` in their code: - https://github.com/FelisCatus/SwitchyOmega (843 stars, proxy switch, custom logger) - https://github.com/AppGyver/steroids (237 stars, PhoneGap extension, throw and crash) -
benjamingr revised this gist
Jan 27, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,7 +14,7 @@ This document attempts to offer a standard way for promise libraries and potenti ##The hook In order to handle rejections the following new events will be fired on `process`: ###Event 'possiblyUnhandledRejection': -
benjamingr revised this gist
Jan 8, 2015 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -97,6 +97,16 @@ These were libraries and projects using `onPossiblyUnhandledRejection` in their None that I am aware of. No one is currently firing events by these names in NodeJS code in GitHub. ##In other languages Promises as an abstraction are indeed not unique to JavaScript - let's explore what other languages do. - in C# 4.0 and .NET in general - such a hook exists for Task with an unterminated error handler will crash your application unless you add a `TaskScheduler.UnobservedTaskException` event handler. In 4.5 you can handle errors yourself (like `.catch`). - In Scala it used to silent fail (lots of surprised answers in SO - e.g. http://stackoverflow.com/questions/24453080/) but that upset people https://groups.google.com/forum/#!searchin/scala-user/The$20silence$20of$20failed$20futures/scala-user/1X2QISf3604/2dw0XhMh0RUJ , they now intend to support that case. - Dart futures already do this forwarding rejections to the global error handler. So overall it seems like other programming environments support a unhandled rejection hander. Note that JavaScript is pretty special in that it is the only case I know of where a lot of different implementations of this abstract concept exist. ##Future work Add a similar solution for promise libraries in browsers, possibly the [WhatWG proposal](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0024.html). -
benjamingr revised this gist
Jan 8, 2015 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,8 @@ Possibly Unhandled Rejection NodeJS Promise Hook ---------------------------------------- ###Unhandled Rejection Tracking Several promise libraries such as [bluebird](https://github.com/petkaantonov/bluebird) and [when](https://github.com/cujojs/when/blob/master/docs/api.md) as well as some native promise implementations offer potentially unhandled rejection tracking. This means that the following: -
benjamingr created this gist
Jan 8, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,107 @@ Possibly Unhandled Rejection NodeJS Promise Hook ---------------------------------------- ##Unhandled Rejection Tracking Several promise libraries such as [bluebird](https://github.com/petkaantonov/bluebird) and [when](https://github.com/cujojs/when/blob/master/docs/api.md) as well as some native promise implementations offer potentially unhandled rejection tracking. This means that the following: Promise.reject(new Error("err")); // never attach a `catch` Does not get silently suppressed being an error but instead gets logged to the console or otherwise treated by the promise library. A common request is a way to handle rejection application wide. NodeJS code often includes several copies of the same promise library or different promise libraries and it is currently difficult to install a global hook on potentially unhandled rejections. For example code using Bluebird for concurrency, [akamai](https://github.com/mrlannigan/node-akamai) for their API, [bookshelf](https://github.com/tgriesser/bookshelf) as an ORM and [request-promise](https://github.com/tyabonil/request-promise) for web requests uses 4 promise libraries already - 3 Bluebirds and a WhenJS. If someone wants to log errors for all tracked unhandled rejections they'd have to add at least _four_ handlers - if they miss any their code won't do what they expect. This document attempts to offer a standard way for promise libraries and potentially native promises in Node to communicate they have detected an unhandled rejection. ##The hook In order to handle rejections the following new evers will be fired on `process`: ###Event 'possiblyUnhandledRejection': Emitted whenever a possibly unhandled rejection is detected. This event is emitted with the following arguments: - `reason` the rejection reason of the promise susprected in having an unhandled rejection - `p` the promise suspected in having an unhandled rejection itself. ```js process.on('possiblyUnhandledRejection', function(reason, p){ console.log("Possibly Unhandled Rejection at: Promise ", p, " reason: ", reason); // application specific logging here }); ``` ###Event 'possiblyUnhandledRejectionHandled': Emitted whenever a possibly unhandled rejection was mistakenly identified and was eventually handled. For example if the promise library made a mistake considering `p` in the following case unhandled: let p = Promise.reject(new Error("err")); setTimeout(() => p.catch(function(){}), 86400); This event is emitted with the following arguments: - `p` the promise who was believed to be an unhandled rejection. This event is useful in order to recover from detection mistakes. While in my experience this rarely happens in practice this additional hook helps in such cases. ##Statistics I have collected statistics about usage of `onPossiblyUnhandledRejection` from GitHub: Large (>1000 stars) libraries typically don't change onPossiblyUnhandledRejection, the largest ORMS: Sequelize, Waterline and Bookshelf do not hook on it however users of those libraries sometimes do. It also very common for people to override it in test code. These were libraries and projects using `onPossiblyUnhandledRejection` in their code: - https://github.com/FelisCatus/SwitchyOmega (843 stars, proxy switch, custom logger) - https://github.com/AppGyver/steroids (237 stars, PhoneGap extension, throw and crash) - https://github.com/att/rcloud (153 stars, AT&T R script cloud thing, defaults to custom logging) - https://github.com/simplyianm/githubfollowers/ (101 stars, defaults to log and adds a console log, rather pointless call) - https://github.com/ripple/gatewayd (89 stars, framework for financial network, custom logging) - https://github.com/tyabonil/request-promise/ (50 stars, promisified package, actual custom logic) - https://github.com/mikermcneil/waterline2/ (20 stars, waterline ORM proposed next generation, defaults to suppress behavior) - https://github.com/PhilWaldmann/openrecord (19 stars, ORM, lets user configure, defaults to log) - https://github.com/wikimedia/restbase (14 stars, Wikipedia people, log) - https://github.com/zaggino/brackets-snippets (14 stars, overrides to crash). - https://github.com/mozilla/fxa-oauth-server (9 stars, by Mozilla, undefined passed to get Q like behavior). - https://github.com/kenspirit/kanban-cfd (8 stars, Kanban graph visualization, crash) - https://github.com/mattlewis92/angular-bluebird-promises (6 stars, bluebird for angular, passes noop (this is slighly upsetting :D)) - https://github.com/Evisions/vertebrae (5 stars, Backbone extension, custom logging) - https://github.com/mzgol/check-dependencies (6 stars, npm dependency check, suppress (TODO above)) - https://github.com/speech/speech.js (3 stars, namecoin domain thing, crash) - https://github.com/iarna/promisable (3 stars, promises module, references that it acts like `throw e;` not actual bluebird) - https://github.com/maseb/thicket (2 stars, framework, crash) - https://github.com/sebinsua/neo4j-promised (2 stars, custom logic to overcome heavior change) - https://github.com/ELLIOTTCABLE/wikipedi.as (2 stars, wikipedia thing, log) - https://github.com/vkarpov15/wagner-core (1 star, framework, suppress (comment above "swallow bluebird annoying error messages")) - https://github.com/jdeanwaite/eDVR (1 star, DVR, defaults to log with default to throw commented) - https://github.com/opinsys/puavo-ticket (1 star, ticket system, custom logging) - https://github.com/wikimedia/mediawiki-services-restbase (0 stars, mirror of Wikipedia service, logging) - https://github.com/ZJONSSON/express-clues (1 star, express api wrapper, suppress) - https://github.com/AaronO/q-bluebird (0 stars, Q API Bluebird wrapper, custom logging) - https://github.com/mattlewis92/generator-nasty (0 stars, yeoman generator, defaults to log) - https://github.com/bjoerge/proxyreload (0 stars, proxy, passes null) - https://github.com/ericnorris/node-cdb (0 stars, cdb implementation, ignores) - https://github.com/shanesmith/gerrit-cli (0 stars, no diea, throws) - https://github.com/Bornholm/nap-bootstrap (0 stars, overrides to crash). - https://github.com/mcirclek/website-client (0 stars, defaults to custom logging) - https://github.com/chrisdoble/amd-to-closure (0 stars, converts AMD to closure compiler syntax, suppress) - https://github.com/colonyamerican/cah-logger (0 stars, overrides to crash) - https://github.com/micirclek/cki-portal (0 stars, site, suppress) - https://github.com/dinexcode/dnxapp-gatewayd (0 stars, unclear, log) - https://github.com/srcspider/prototyping (0 stars, seed, defaults to crash) - https://github.com/martin-liu/m-sails/blob/f02f33a60c424517168b365c0c61da4ad85b8ba6/api/coffee/services/Promise.coffee (0 stars, personal project) - https://github.com/danprince/cyvasse (Game, 0 stars, undefined passed to get Q like behavior, lots (100) like this using bundler.js) ##Backwards incompatible changes None that I am aware of. No one is currently firing events by these names in NodeJS code in GitHub. ##Future work Add a similar solution for promise libraries in browsers, possibly the [WhatWG proposal](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0024.html). ##Related work: - [Promise Inspection Protocol](https://gist.github.com/kriskowal/8948969) - [Bluebird's onPossiblyUnhandledRejection](https://github.com/petkaantonov/bluebird/blob/master/API.md#promiseonpossiblyunhandledrejectionfunction-handler---undefined) - [WhatWG browser proposal](http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0024.html)