From af3aa682ac534bb55765f5fef2755a88e5ff2580 Mon Sep 17 00:00:00 2001 From: Refael Ackermann Date: Thu, 27 Apr 2017 21:57:12 -0400 Subject: [PATCH] util: add callbackify Add `util.callbackify(function)` for creating callback style functions from functions returning a `Thenable` PR-URL: https://github.com/nodejs/node/pull/12712 Fixes: https://github.com/nodejs/CTC/issues/109 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Teddy Katz Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig Reviewed-By: Timothy Gu Reviewed-By: Anna Henningsen --- doc/api/util.md | 59 +++++ lib/internal/errors.js | 1 + lib/util.js | 50 ++++ .../uncaught-exceptions/callbackify1.js | 15 ++ .../uncaught-exceptions/callbackify2.js | 22 ++ test/parallel/test-util-callbackify.js | 227 ++++++++++++++++++ 6 files changed, 374 insertions(+) create mode 100644 test/fixtures/uncaught-exceptions/callbackify1.js create mode 100644 test/fixtures/uncaught-exceptions/callbackify2.js create mode 100644 test/parallel/test-util-callbackify.js diff --git a/doc/api/util.md b/doc/api/util.md index 839bdadf76..9fce6294e1 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -10,6 +10,64 @@ module developers as well. It can be accessed using: const util = require('util'); ``` +## util.callbackify(original) + + +* `original` {Function} An `async` function +* Returns: {Function} a callback style function + +Takes an `async` function (or a function that returns a Promise) and returns a +function following the Node.js error first callback style. In the callback, the +first argument will be the rejection reason (or `null` if the Promise resolved), +and the second argument will be the resolved value. + +For example: + +```js +const util = require('util'); + +async function fn() { + return await Promise.resolve('hello world'); +} +const callbackFunction = util.callbackify(fn); + +callbackFunction((err, ret) => { + if (err) throw err; + console.log(ret); +}); +``` + +Will print: + +```txt +hello world +``` + +*Note*: + +* The callback is executed asynchronously, and will have a limited stack trace. +If the callback throws, the process will emit an [`'uncaughtException'`][] +event, and if not handled will exit. + +* Since `null` has a special meaning as the first argument to a callback, if a +wrapped function rejects a `Promise` with a falsy value as a reason, the value +is wrapped in an `Error` with the original value stored in a field named +`reason`. + ```js + function fn() { + return Promise.reject(null); + } + const callbackFunction = util.callbackify(fn); + + callbackFunction((err, ret) => { + // When the Promise was rejected with `null` it is wrapped with an Error and + // the original value is stored in `reason`. + err && err.hasOwnProperty('reason') && err.reason === null; // true + }); + ``` + ## util.debuglog(section)