Write promisifyAll(obj). For every method of obj, it adds a promise-returning version named after it with Async on the end: get gets a getAsync. It returns obj itself, and the original methods keep working as before.
The methods take a Node-style callback: their arguments, then a callback (error, result). Each Async version takes the same arguments without the callback and returns a promise. The promise rejects with error when the callback gets a truthy one, and fulfills with result otherwise, even when result is falsy, like 0. If the method throws, the promise rejects with what it threw.
Calling obj.getAsync(…) runs get with this set to obj, so methods that use this keep working.
A method is any property of obj whose value is a function, enumerable or not: its own, and those it inherits through its prototype chain, such as the methods of its class and of the classes that class extends. constructor and the methods of Object.prototype, like toString, don't count, and neither do properties that aren't functions.
When a subclass overrides a method, getAsync uses the subclass's version: the one obj.get gives you.
class Store {
constructor() {
this.items = new Map();
}
get(key, callback) {
setTimeout(() => {
if (this.items.has(key)) callback(null, this.items.get(key));
else callback(new Error("No such key: " + key));
}, 10);
}
set(key, value, callback) {
this.items.set(key, value);
setTimeout(() => callback(null), 10);
}
}
const store = promisifyAll(new Store());
await store.setAsync("theme", "dark"); // undefined
await store.getAsync("theme"); // "dark"
await store.getAsync("font"); // rejects with Error: No such key: font
typeof store.itemsAsync; // "undefined": items isn't a method
const obj = {
read(callback) {
callback(null, "data");
},
};
expect(promisifyAll(obj)).toBe(obj);
const api = promisifyAll({
read(callback) {
callback(null, "data");
},
write(text, callback) {
callback(null, text.length);
},
});
const reading = api.readAsync();
expect(reading).toBeInstanceOf(Promise);
await expect(reading).resolves.toBe("data");
await expect(api.writeAsync("hello")).resolves.toBe(5);
const clock = useFakeTimers();
const api = promisifyAll({
read(name, callback) {
setTimeout(() => callback(null, "contents of " + name), 100);
},
});
let result;
api.readAsync("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 add = spy((a, b, callback) => callback(null, a + b));
const api = promisifyAll({ add });
await expect(api.addAsync(2, 3)).resolves.toBe(5);
const call = add.calls[0];
expect(call.args).toHaveLength(3);
expect(call.args.slice(0, 2)).toEqual([2, 3]);
expect(typeof call.args[2]).toBe("function");
expect(call.this).toBe(api);
const error = new Error("disk full");
const api = promisifyAll({
save(callback) {
callback(error);
},
count(callback) {
callback(null, 0);
},
});
await expect(api.saveAsync()).rejects.toBe(error);
await expect(api.countAsync()).resolves.toBe(0);
const error = new TypeError("bad input");
const api = promisifyAll({
parse() {
throw error;
},
});
let promise;
expect(() => {
promise = api.parseAsync("x");
}).not.toThrow();
await expect(promise).rejects.toBe(error);
class Connection {
ping(callback) {
callback(null, "pong");
}
}
class Database extends Connection {
constructor() {
super();
this.rows = { 1: "Ada" };
}
find(id, callback) {
callback(null, this.rows[id]);
}
}
const db = promisifyAll(new Database());
await expect(db.findAsync(1)).resolves.toBe("Ada");
await expect(db.pingAsync()).resolves.toBe("pong");
class Base {
describe(callback) {
callback(null, "base");
}
}
class Child extends Base {
describe(callback) {
callback(null, "child");
}
}
const child = promisifyAll(new Child());
await expect(child.describeAsync()).resolves.toBe("child");
class Service {
constructor() {
this.retries = 3;
}
start(callback) {
callback(null);
}
}
const service = promisifyAll(new Service());
expect(typeof service.startAsync).toBe("function");
expect(service.constructorAsync).toBeUndefined();
expect(service.toStringAsync).toBeUndefined();
expect(service.hasOwnPropertyAsync).toBeUndefined();
expect(service.retriesAsync).toBeUndefined();
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 promisifyAll. 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.