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