index.js 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. var Promise = require('any-promise')
  2. var assert = require('assert')
  3. module.exports = thenify
  4. /**
  5. * Turn async functions into promises
  6. *
  7. * @param {Function} fn
  8. * @return {Function}
  9. * @api public
  10. */
  11. function thenify(fn, options) {
  12. assert(typeof fn === 'function')
  13. return createWrapper(fn, options)
  14. }
  15. /**
  16. * Turn async functions into promises and backward compatible with callback
  17. *
  18. * @param {Function} fn
  19. * @return {Function}
  20. * @api public
  21. */
  22. thenify.withCallback = function (fn, options) {
  23. assert(typeof fn === 'function')
  24. options = options || {}
  25. options.withCallback = true
  26. return createWrapper(fn, options)
  27. }
  28. function createCallback(resolve, reject, multiArgs) {
  29. // default to true
  30. if (multiArgs === undefined) multiArgs = true
  31. return function(err, value) {
  32. if (err) return reject(err)
  33. var length = arguments.length
  34. if (length <= 2 || !multiArgs) return resolve(value)
  35. if (Array.isArray(multiArgs)) {
  36. var values = {}
  37. for (var i = 1; i < length; i++) values[multiArgs[i - 1]] = arguments[i]
  38. return resolve(values)
  39. }
  40. var values = new Array(length - 1)
  41. for (var i = 1; i < length; ++i) values[i - 1] = arguments[i]
  42. resolve(values)
  43. }
  44. }
  45. function createWrapper(fn, options) {
  46. options = options || {}
  47. var name = fn.name;
  48. name = (name || '').replace(/\s|bound(?!$)/g, '')
  49. var newFn = function () {
  50. var self = this
  51. var len = arguments.length
  52. if (options.withCallback) {
  53. var lastType = typeof arguments[len - 1]
  54. if (lastType === 'function') return fn.apply(self, arguments)
  55. }
  56. var args = new Array(len + 1)
  57. for (var i = 0; i < len; ++i) args[i] = arguments[i]
  58. var lastIndex = i
  59. return new Promise(function (resolve, reject) {
  60. args[lastIndex] = createCallback(resolve, reject, options.multiArgs)
  61. fn.apply(self, args)
  62. })
  63. }
  64. Object.defineProperty(newFn, 'name', { value: name })
  65. return newFn
  66. }