function.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /** @license MIT License (c) copyright 2013-2014 original author or authors */
  2. /**
  3. * Collection of helper functions for wrapping and executing 'traditional'
  4. * synchronous functions in a promise interface.
  5. *
  6. * @author Brian Cavalier
  7. * @contributor Renato Zannon
  8. */
  9. (function(define) {
  10. define(function(require) {
  11. var when = require('./when');
  12. var attempt = when['try'];
  13. var _liftAll = require('./lib/liftAll');
  14. var _apply = require('./lib/apply')(when.Promise);
  15. var slice = Array.prototype.slice;
  16. return {
  17. lift: lift,
  18. liftAll: liftAll,
  19. call: attempt,
  20. apply: apply,
  21. compose: compose
  22. };
  23. /**
  24. * Takes a function and an optional array of arguments (that might be promises),
  25. * and calls the function. The return value is a promise whose resolution
  26. * depends on the value returned by the function.
  27. * @param {function} f function to be called
  28. * @param {Array} [args] array of arguments to func
  29. * @returns {Promise} promise for the return value of func
  30. */
  31. function apply(f, args) {
  32. // slice args just in case the caller passed an Arguments instance
  33. return _apply(f, this, args == null ? [] : slice.call(args));
  34. }
  35. /**
  36. * Takes a 'regular' function and returns a version of that function that
  37. * returns a promise instead of a plain value, and handles thrown errors by
  38. * returning a rejected promise. Also accepts a list of arguments to be
  39. * prepended to the new function, as does Function.prototype.bind.
  40. *
  41. * The resulting function is promise-aware, in the sense that it accepts
  42. * promise arguments, and waits for their resolution.
  43. * @param {Function} f function to be bound
  44. * @param {...*} [args] arguments to be prepended for the new function @deprecated
  45. * @returns {Function} a promise-returning function
  46. */
  47. function lift(f /*, args... */) {
  48. var args = arguments.length > 1 ? slice.call(arguments, 1) : [];
  49. return function() {
  50. return _apply(f, this, args.concat(slice.call(arguments)));
  51. };
  52. }
  53. /**
  54. * Lift all the functions/methods on src
  55. * @param {object|function} src source whose functions will be lifted
  56. * @param {function?} combine optional function for customizing the lifting
  57. * process. It is passed dst, the lifted function, and the property name of
  58. * the original function on src.
  59. * @param {(object|function)?} dst option destination host onto which to place lifted
  60. * functions. If not provided, liftAll returns a new object.
  61. * @returns {*} If dst is provided, returns dst with lifted functions as
  62. * properties. If dst not provided, returns a new object with lifted functions.
  63. */
  64. function liftAll(src, combine, dst) {
  65. return _liftAll(lift, combine, dst, src);
  66. }
  67. /**
  68. * Composes multiple functions by piping their return values. It is
  69. * transparent to whether the functions return 'regular' values or promises:
  70. * the piped argument is always a resolved value. If one of the functions
  71. * throws or returns a rejected promise, the composed promise will be also
  72. * rejected.
  73. *
  74. * The arguments (or promises to arguments) given to the returned function (if
  75. * any), are passed directly to the first function on the 'pipeline'.
  76. * @param {Function} f the function to which the arguments will be passed
  77. * @param {...Function} [funcs] functions that will be composed, in order
  78. * @returns {Function} a promise-returning composition of the functions
  79. */
  80. function compose(f /*, funcs... */) {
  81. var funcs = slice.call(arguments, 1);
  82. return function() {
  83. var thisArg = this;
  84. var args = slice.call(arguments);
  85. var firstPromise = attempt.apply(thisArg, [f].concat(args));
  86. return when.reduce(funcs, function(arg, func) {
  87. return func.call(thisArg, arg);
  88. }, firstPromise);
  89. };
  90. }
  91. });
  92. })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });