makepromise
Version:
Make a Promise from a function with a callback and preserve its error stack.
56 lines (50 loc) • 1.82 kB
JavaScript
let erotic = require('erotic'); if (erotic && erotic.__esModule) erotic = erotic.default;
// /**
// * @param {number} length
// * @param {number} i
// * @param {!Function} fn
// */
// function checkArgumentIndex(length, i, fn) {
// if (i > length - 2) {
// throw new Error(`Function${fn.name ? ` ${fn.name}` : ''} does not accept that many arguments (max ${length - 1} + callback).`)
// }
// }
/**
* Get a promise from a function which otherwise accepts a callback.
* @param {Function} fn A function to promisify.
* @param {*|Array<*>} [args] An array of arguments to use in the call, or a single argument.
* @param {*} [resolveValue] A value to override the value with which the promise will be resolved.
* @returns {Promise<*>} A promise resolved on callback invocation without an error and rejected on callback called with an error.
*/
async function makePromise(fn, args, resolveValue) {
const er = erotic(true)
if (typeof fn != 'function') {
throw new Error('Function must be passed.')
}
const { length: fnLength } = fn
if (!fnLength) {
throw new Error(`Function${fn.name ? ` ${fn.name}` : ''} does not accept any arguments.`)
}
const res = await new Promise((resolve, reject)=> {
const cb = (err, res) => {
if (err) {
const error = er(err)
return reject(error)
}
return resolve(resolveValue || res)
}
let allArgs = [cb]
if (Array.isArray(args)) {
// args.forEach((arg, i) => {
// checkArgumentIndex(fnLength, i, fn)
// })
allArgs = [...args, cb]
} else if (Array.from(arguments).length > 1) { // args passed as a single argument, not array
// checkArgumentIndex(fnLength, 0, fn)
allArgs = [args, cb]
}
fn(...allArgs)
})
return res
}
module.exports = makePromise