/** @license MIT License (c) copyright 2013-2014 original author or authors */ /** * Collection of helper functions for wrapping and executing 'traditional' * synchronous functions in a promise interface. * * @author Brian Cavalier * @contributor Renato Zannon */ (function(define) { define(function(require) { var when = require('./when'); var attempt = when['try']; var _liftAll = require('./lib/liftAll'); var _apply = require('./lib/apply')(when.Promise); var slice = Array.prototype.slice; return { lift: lift, liftAll: liftAll, call: attempt, apply: apply, compose: compose }; /** * Takes a function and an optional array of arguments (that might be promises), * and calls the function. The return value is a promise whose resolution * depends on the value returned by the function. * @param {function} f function to be called * @param {Array} [args] array of arguments to func * @returns {Promise} promise for the return value of func */ function apply(f, args) { // slice args just in case the caller passed an Arguments instance return _apply(f, this, args == null ? [] : slice.call(args)); } /** * Takes a 'regular' function and returns a version of that function that * returns a promise instead of a plain value, and handles thrown errors by * returning a rejected promise. Also accepts a list of arguments to be * prepended to the new function, as does Function.prototype.bind. * * The resulting function is promise-aware, in the sense that it accepts * promise arguments, and waits for their resolution. * @param {Function} f function to be bound * @param {...*} [args] arguments to be prepended for the new function @deprecated * @returns {Function} a promise-returning function */ function lift(f /*, args... */) { var args = arguments.length > 1 ? slice.call(arguments, 1) : []; return function() { return _apply(f, this, args.concat(slice.call(arguments))); }; } /** * Lift all the functions/methods on src * @param {object|function} src source whose functions will be lifted * @param {function?} combine optional function for customizing the lifting * process. It is passed dst, the lifted function, and the property name of * the original function on src. * @param {(object|function)?} dst option destination host onto which to place lifted * functions. If not provided, liftAll returns a new object. * @returns {*} If dst is provided, returns dst with lifted functions as * properties. If dst not provided, returns a new object with lifted functions. */ function liftAll(src, combine, dst) { return _liftAll(lift, combine, dst, src); } /** * Composes multiple functions by piping their return values. It is * transparent to whether the functions return 'regular' values or promises: * the piped argument is always a resolved value. If one of the functions * throws or returns a rejected promise, the composed promise will be also * rejected. * * The arguments (or promises to arguments) given to the returned function (if * any), are passed directly to the first function on the 'pipeline'. * @param {Function} f the function to which the arguments will be passed * @param {...Function} [funcs] functions that will be composed, in order * @returns {Function} a promise-returning composition of the functions */ function compose(f /*, funcs... */) { var funcs = slice.call(arguments, 1); return function() { var thisArg = this; var args = slice.call(arguments); var firstPromise = attempt.apply(thisArg, [f].concat(args)); return when.reduce(funcs, function(arg, func) { return func.call(thisArg, arg); }, firstPromise); }; } }); })(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });