Write promisify(fn). fn is a callback-style function: it takes its arguments followed by a callback (error, result), as Node's fs.readFile does. promisify returns a new function that takes the same arguments without the callback, calls fn with them plus a callback of its own, and returns a promise.
The promise rejects with error when the callback gets one (any truthy error). Otherwise it fulfills with result, even when result is falsy, like 0 or "". If fn throws, the promise rejects with what it threw, so calling the new function never throws. Keep this, so methods can be promisified.
function readConfig(name, callback) {
setTimeout(() => callback(null, { name, debug: true }), 100);
}
const readConfigAsync = promisify(readConfig);
const config = await readConfigAsync("app"); // { name: "app", debug: true }
const ready = promisify((callback) => callback(null, "ok"));
expect(typeof ready).toBe("function");
const promise = ready();
expect(promise).toBeInstanceOf(Promise);
await promise;
const fn = spy((a, b, callback) => callback(null, a + b));
await promisify(fn)(2, 3);
const args = fn.calls[0].args;
expect(args).toHaveLength(3);
expect(args.slice(0, 2)).toEqual([2, 3]);
expect(typeof args[2]).toBe("function");
const clock = useFakeTimers();
const read = promisify((name, callback) => {
setTimeout(() => callback(null, "contents of " + name), 100);
});
let result;
read("notes.txt").then((value) => {
result = value;
});
await clock.tickAsync(99);
expect(result).toBeUndefined();
await clock.tickAsync(1);
expect(result).toBe("contents of notes.txt");
const error = new Error("ENOENT");
const read = promisify((name, callback) => callback(error));
await expect(read("missing.txt")).rejects.toBe(error);
const zero = promisify((callback) => callback(null, 0));
const empty = promisify((callback) => callback(undefined, ""));
await expect(zero()).resolves.toBe(0);
await expect(empty()).resolves.toBe("");
const db = {
prefix: "user:",
get: promisify(function (id, callback) {
callback(null, this.prefix + id);
}),
};
await expect(db.get(7)).resolves.toBe("user:7");
const error = new TypeError("bad input");
const parse = promisify(() => {
throw error;
});
let promise;
expect(() => {
promise = parse("x");
}).not.toThrow();
await expect(promise).rejects.toBe(error);
Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.
Ctrl + Enter runs the tests (⌘ + Enter on a Mac).
I'm here to help with Promisify. I give hints, never the solution, so you get to solve it yourself. Ask for a hint, select code to ask about it, or press Ask Tuto why on a failing test.
Your first 3 answers need no account. for free to keep asking.