AniUI Academy

Promisify a callback API

easyAsync & Promises+150 XPPractice

Plenty of libraries still take a callback as their last argument and call it with (error, value). Mixing that style with async/await is painful, so the usual fix is a small adapter written once.

Implement promisify(fn). It returns a new function that takes the same arguments as fn minus the trailing callback, and returns a Promise. Call fn with those arguments plus a callback of your own. When that callback receives a truthy first argument, reject with it. Otherwise resolve with the second argument, which may be undefined if the callback was called with only the error slot.

Arguments

fnFunction
A function whose last argument is an error-first callback (error, value).

Returns

Function — A function that forwards its arguments to fn and returns a Promise resolving with the callback value or rejecting with the callback error.

Examples

const readValue = (key, cb) => setTimeout(() => cb(null, "v:" + key), 5);
const read = promisify(readValue);
const value = await read("theme");
// value === "v:theme"

Call the wrapper like the original, minus the callback.

const failing = promisify((cb) => cb(new Error("disk offline")));
try {
  await failing();
} catch (error) {
  // error.message === "disk offline"
}

A truthy first callback argument becomes a rejection.

What it has to do

  • The returned function always returns a Promise.
  • Forward every argument it is given to fn, in order, before the callback.
  • Resolve with the callback's second argument when the first is falsy.
  • Reject with the callback's first argument when it is truthy.

Notes

  • Pass this through with fn.call(this, ...) so the wrapped function still works when used as a method.
  • Node's util.promisify has quirks for legacy APIs like fs.exists; this version only handles the standard (error, value) shape.

Stuck? The javascript course covers everything this challenge needs.

Try it yourself
Loading playground...
5 tests · +150 XP

Discussion

Sign in to post
Sign in to join the conversation.Sign in

No comments yet. Be the first to say something.