Question presented to candidate: "You're given a legacy function like readFile(path, (err, data) => {...}) using Node's classic error-first callback convention. Write a real, generic helper that converts ANY such function into one that returns a Promise instead."
What a strong answer should cover:
- 📌 Interview term: the error-first (Node-style) callback convention — the classic pattern this conversion targets: a callback's FIRST argument is either an
Error(on failure) ornull/undefined(on success), with subsequent arguments carrying the real result. - 📌 Interview term: wrapping with
new Promise— the real, direct answer: construct anew Promise((resolve, reject) => { ... }), calling the original callback-based function INSIDE the executor, and inside that callback, callingreject(err)iferris truthy, otherwiseresolve(result). - 📌 Interview term: the real, direct answer to the prompt — verified directly: a real, generic
promisify(fn)helper — written once, reusable for ANY error-first function, not hardcoded to one specific function — was verified correctlyresolveing on a real success case andrejecting on a real error case, matching the original callback's own real behavior exactly. - 📌 Interview term: Node's own built-in
util.promisify— verified directly: Node's REAL, built-inutil.promisify()does the IDENTICAL conversion, confirmed producing the same real result as the hand-written version for the identical legacy function — a real, standard tool that makes hand-rolling this conversion unnecessary in Node code specifically. - A precise answer names the real, general SHAPE of the conversion:
(...args) => new Promise((resolve, reject) => fn(...args, (err, result) => err ? reject(err) : resolve(result)))— genuinely works for any function following the error-first convention, regardless of how many success-value arguments it has (with the honest caveat that a callback returning MULTIPLE success values needs a small, deliberate adjustment, since a Promise can only resolve with one value).
Clarifying questions expected:
- None — this is a definitional/technical question; writing a real, GENERIC helper (not a one-off hardcoded wrapper for a single function) is the strong signal.
Code / implementation expected: Yes — a real, generic promisify helper, verified working for both the success and error paths of a real legacy callback function, is the clearest, most convincing demonstration.