User Rating 0.0
Total Usage 0 times
Callback Code (Input)
Promise Code (Output)
Converted code will appear here...
Is this tool helpful?

Your feedback helps us improve.

About

Legacy Node.js and browser codebases rely on error-first callbacks: fn(err, result). Migrating these to ES6 Promises is not a cosmetic change. Incorrect wrapping causes silent swallowed errors, unhandled rejections that crash processes, and subtle race conditions when multiple callbacks fire. This tool parses your callback-based JavaScript and generates correct Promise-wrapped equivalents using promisify patterns, inline new Promise constructors, or full async/await refactors. It handles single-result callbacks, multi-argument callbacks with named destructuring, and .bind() context patterns.

The converter assumes the Node.js error-first convention where the first callback argument is always err. Functions that deviate from this pattern (e.g., event emitters, streams with multiple events) require manual refactoring. The tool does not execute your code. It performs string-level pattern transformation. Always review generated output before deploying to production.

callback to promise es6 promisify javascript converter async await promise wrapper node.js callback code refactoring

Formulas

The core transformation follows the error-first callback unwrapping pattern. Given a function fn that accepts arguments followed by a callback cb(err, result), the promisified version is constructed as:

promisify(fn) = (...args) new Promise((resolve, reject) fn(...args, (err, result) err ? reject(err) : resolve(result)))

Where fn = original callback-accepting function, args = all arguments except the trailing callback, err = first callback parameter (error or null), result = second callback parameter (success value).

For multi-argument callbacks with n results, the resolution maps named keys:

cb(err, v1, v2, ..., vn) resolve({key1: v1, key2: v2, ..., keyn: vn})

The detection algorithm scores callback likelihood using: position of parameter (last = +3), naming convention matching cb/callback/done/next (= +2), error-first pattern in body (= +2). A score 4 triggers automatic conversion.

Reference Data

PatternCallback SignaturePromise EquivalentNotes
Simple error-firstfn(cb)await promisify(fn)()Most common Node.js pattern
With argumentsfn(arg1, cb)await promisify(fn)(arg1)Callback is always last parameter
Bound methodobj.fn.bind(obj)promisify(obj.fn.bind(obj))Preserves this context
Multi-resultcb(err, a, b)Resolves to {a, b}Named via argumentNames symbol
No error paramfn(result)Manual wrap requiredNon-standard, flagged as warning
Nested callbacksfn1(fn2(fn3))Chained await callsEliminates callback hell
fs.readFilefs.readFile(path, cb)await readFile(path)Node.js 16+ has native fs/promises
setTimeoutsetTimeout(cb, ms)new Promise(rsetTimeout(r, ms))Special case, no error argument
Event-styleemitter.on(event, cb)Not directly promisifiableUse once from events module
Conditional callbackif (cb) cb()Requires manual refactorOptional callbacks are ambiguous
Express middlewarefn(req, res, next)Wrap in async handlernext is not error-first
Promisify whole moduleMultiple methodsLoop + promisify eachUse promisifyAll pattern

Frequently Asked Questions

The converter assumes the Node.js standard where the first argument to the callback is err (either an Error object or null). If your function passes the result as the first argument (e.g., setTimeout), the generated Promise wrapper will incorrectly reject on truthy values. The tool flags these non-standard patterns with a warning comment in the output. You must manually adjust the reject/resolve logic for such cases.
A Promise can only settle once. If the original function invokes the callback more than once (common in streaming or event-based APIs), only the first invocation takes effect. Subsequent calls are silently ignored by the Promise constructor. The converter cannot detect multi-fire callbacks via static analysis. If you suspect this pattern, use an EventEmitter or Observable wrapper instead of Promises.
Node.js 8+ includes util.promisify which handles util.promisify.custom symbols. This tool generates equivalent code for environments without util (browsers, older runtimes) or when you need the generated source for bundling. For Node.js 16+, consider using the native fs/promises API directly rather than wrapping fs callbacks.
Yes. When the input contains nested callbacks (function A calls function B in its callback, which calls function C), the converter flattens them into sequential await statements. Each level of nesting becomes a separate const assignment. Variable names are preserved from the original callback parameters. Deeply nested chains (> 5 levels) may produce verbose output that benefits from manual cleanup.
When the converter detects obj.method.bind(obj), it preserves the binding in the promisified wrapper: promisify(obj.method.bind(obj)). Without bind, methods that reference this internally will throw or return undefined. The tool also supports arrow-function-based alternatives where this is lexically bound.
Three modes: (1) Inline Promise wraps each call in new Promise directly, best for one-off conversions. (2) Utility Wrapper generates a reusable promisify function, ideal when converting multiple functions in a module. (3) Async/Await produces the most modern output with try/catch error handling, recommended for new codebases targeting ES2017+.