-
Notifications
You must be signed in to change notification settings - Fork 31
/
promisify.js
63 lines (53 loc) · 2.21 KB
/
promisify.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Symbols is a better way to do this, but not all browsers have good support,
// so instead we'll just make do with a very unlikely string.
const customArgumentsToken = "__ES6-PROMISIFY--CUSTOM-ARGUMENTS__";
/**
* promisify()
* Transforms callback-based function -- func(arg1, arg2 .. argN, callback) --
* into an ES6-compatible Promise. Promisify provides a default callback of the
* form (error, result) and rejects when `error` is truthy.
*
* @param {function} original - The function to promisify
* @return {function} A promisified version of `original`
*/
export function promisify(original) {
// Ensure the argument is a function
if (typeof original !== "function") {
throw new TypeError("Argument to promisify must be a function");
}
// If the user has asked us to decode argument names for them, honour that
const argumentNames = original[customArgumentsToken];
// If the user has supplied a custom Promise implementation, use it.
// Otherwise fall back to whatever we can find on the global object.
const ES6Promise = promisify.Promise || Promise;
// If we can find no Promise implemention, then fail now.
if (typeof ES6Promise !== "function") {
throw new Error("No Promise implementation found; do you need a polyfill?");
}
return function (...args) {
return new ES6Promise((resolve, reject) => {
// Append the callback bound to the context
args.push(function callback(err, ...values) {
if (err) {
return reject(err);
}
if (values.length === 1 || !argumentNames) {
return resolve(values[0]);
}
const o = {};
values.forEach((value, index) => {
const name = argumentNames[index];
if (name) {
o[name] = value;
}
});
resolve(o);
});
// Call the function.
original.apply(this, args);
});
};
}
// Attach this symbol to the exported function, so users can use it
promisify.argumentNames = customArgumentsToken;
promisify.Promise = undefined;