Callback to Promise Converter
Convert Node.js callback-based functions into Promise-based equivalents. Supports error-first callbacks, context binding, and property preservation.
About
Node.js adopted the error-first callback convention (err, result) before Promises became native in ES2015. Migrating legacy codebases manually is tedious and error-prone. A misplaced reject or a forgotten this binding silently breaks async chains, producing unhandled rejections that crash production processes. This tool parses your callback-style function signatures and generates correct Promise wrappers, preserving static properties and flagging this references that require explicit context. It follows the same pattern used by Node.js core util.promisify and libraries like promo and bluebird.
Limitations: this tool operates on source text, not a full AST. It handles standard patterns reliably but may require manual adjustment for deeply nested or dynamically constructed callbacks. Functions that call their callback multiple times will only resolve the first invocation.
Formulas
The promisification pattern wraps a callback-accepting function f in a Promise constructor. The core transformation follows this structure:
return new Promise((resolve, reject) → {
f.call(ctx, ...args, (err, ...results) → {
if (err) reject(err)
else resolve(results.length ≤ 1 ? results[0] : results)
})
})
}
Where f is the original callback-based function, ctx is the optional this context (defaults to NULL if not provided), args are all arguments except the callback, err follows the Node.js error-first convention (first callback argument), and results captures remaining callback arguments. When results.length ≤ 1, the single value is unwrapped from the array.
Static property preservation uses Object.keys(f).forEach(key → wrapper[key] = f[key]) to copy all enumerable properties from the original function to the promisified wrapper.
Reference Data
| Pattern | Callback Signature | Promise Equivalent | Notes |
|---|---|---|---|
| Error-first | fn(arg, cb(err, res)) | fn(arg).then(res) | Node.js standard |
| No error | fn(arg, cb(res)) | fn(arg).then(res) | Always resolves |
| Multi-result | cb(err, a, b) | resolve([a, b]) | Array destructure |
| Context-bound | obj.method(cb) | promisify(method, obj) | Requires this binding |
| Static props | fn.sync | Copied to wrapper | Object.keys enumeration |
| util.promisify | Node ≥ 8.0 | Native support | Built-in since Node 8 |
| Bluebird | Promise.promisify | Third-party | Adds cancellation support |
| promo | promo(fn) | Lightweight wrapper | Uses es6-promise polyfill |
| pify | pify(fn) | Sindre Sorhus | Supports multi-arg |
| fs.readFile | readFile(path, cb) | readFile(path).then() | Classic example |
| fs.writeFile | writeFile(path, data, cb) | writeFile(path, data).then() | Classic example |
| glob | glob(pattern, cb) | glob(pattern).then() | Has .sync property |
| mkdirp | mkdirp(dir, cb) | mkdirp(dir).then() | Recursive mkdir |
| setTimeout | setTimeout(cb, ms) | Custom wrapper needed | Non-standard signature |
| EventEmitter | on(event, cb) | Not directly promisifiable | Multi-fire pattern |