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 | return _apply(f, this, args || []);
|
37 | }
|
38 |
|
39 | /**
|
40 | * Takes a 'regular' function and returns a version of that function that
|
41 | * returns a promise instead of a plain value, and handles thrown errors by
|
42 | * returning a rejected promise. Also accepts a list of arguments to be
|
43 | * prepended to the new function, as does Function.prototype.bind.
|
44 | *
|
45 | * The resulting function is promise-aware, in the sense that it accepts
|
46 | * promise arguments, and waits for their resolution.
|
47 | * @param {Function} f function to be bound
|
48 | * @param {...*} [args] arguments to be prepended for the new function @deprecated
|
49 | * @returns {Function} a promise-returning function
|
50 | */
|
51 | function lift(f /*, args... */) {
|
52 | var args = arguments.length > 1 ? slice.call(arguments, 1) : [];
|
53 | return function() {
|
54 | return _apply(f, this, args.concat(slice.call(arguments)));
|
55 | };
|
56 | }
|
57 |
|
58 | /**
|
59 | * Apply helper that allows specifying thisArg
|
60 | * @private
|
61 | */
|
62 | function _apply(f, thisArg, args) {
|
63 | return args.length === 0
|
64 | ? attempt.call(thisArg, f)
|
65 | : attempt.apply(thisArg, [f].concat(args));
|
66 | }
|
67 |
|
68 | /**
|
69 | * Lift all the functions/methods on src
|
70 | * @param {object|function} src source whose functions will be lifted
|
71 | * @param {function?} combine optional function for customizing the lifting
|
72 | * process. It is passed dst, the lifted function, and the property name of
|
73 | * the original function on src.
|
74 | * @param {(object|function)?} dst option destination host onto which to place lifted
|
75 | * functions. If not provided, liftAll returns a new object.
|
76 | * @returns {*} If dst is provided, returns dst with lifted functions as
|
77 | * properties. If dst not provided, returns a new object with lifted functions.
|
78 | */
|
79 | function liftAll(src, combine, dst) {
|
80 | return _liftAll(lift, combine, dst, src);
|
81 | }
|
82 |
|
83 | /**
|
84 | * Composes multiple functions by piping their return values. It is
|
85 | * transparent to whether the functions return 'regular' values or promises:
|
86 | * the piped argument is always a resolved value. If one of the functions
|
87 | * throws or returns a rejected promise, the composed promise will be also
|
88 | * rejected.
|
89 | *
|
90 | * The arguments (or promises to arguments) given to the returned function (if
|
91 | * any), are passed directly to the first function on the 'pipeline'.
|
92 | * @param {Function} f the function to which the arguments will be passed
|
93 | * @param {...Function} [funcs] functions that will be composed, in order
|
94 | * @returns {Function} a promise-returning composition of the functions
|
95 | */
|
96 | function compose(f /*, funcs... */) {
|
97 | var funcs = slice.call(arguments, 1);
|
98 |
|
99 | return function() {
|
100 | var thisArg = this;
|
101 | var args = slice.call(arguments);
|
102 | var firstPromise = attempt.apply(thisArg, [f].concat(args));
|
103 |
|
104 | return when.reduce(funcs, function(arg, func) {
|
105 | return func.call(thisArg, arg);
|
106 | }, firstPromise);
|
107 | };
|
108 | }
|
109 | });
|
110 | })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
|
111 |
|
112 |
|