aboutsummaryrefslogtreecommitdiff
path: root/node_modules/when/node.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/when/node.js')
-rw-r--r--node_modules/when/node.js282
1 files changed, 282 insertions, 0 deletions
diff --git a/node_modules/when/node.js b/node_modules/when/node.js
new file mode 100644
index 000000000..61d9453ff
--- /dev/null
+++ b/node_modules/when/node.js
@@ -0,0 +1,282 @@
+/** @license MIT License (c) copyright 2013 original author or authors */
+
+/**
+ * Collection of helpers for interfacing with node-style asynchronous functions
+ * using promises.
+ *
+ * @author Brian Cavalier
+ * @contributor Renato Zannon
+ */
+
+(function(define) {
+define(function(require) {
+
+ var when = require('./when');
+ var _liftAll = require('./lib/liftAll');
+ var setTimer = require('./lib/env').setTimer;
+ var slice = Array.prototype.slice;
+
+ var _apply = require('./lib/apply')(when.Promise, dispatch);
+
+ return {
+ lift: lift,
+ liftAll: liftAll,
+ apply: apply,
+ call: call,
+ createCallback: createCallback,
+ bindCallback: bindCallback,
+ liftCallback: liftCallback
+ };
+
+ /**
+ * Takes a node-style async function and calls it immediately (with an optional
+ * array of arguments or promises for arguments). It returns a promise whose
+ * resolution depends on whether the async functions calls its callback with the
+ * conventional error argument or not.
+ *
+ * With this it becomes possible to leverage existing APIs while still reaping
+ * the benefits of promises.
+ *
+ * @example
+ * function onlySmallNumbers(n, callback) {
+ * if(n < 10) {
+ * callback(null, n + 10);
+ * } else {
+ * callback(new Error("Calculation failed"));
+ * }
+ * }
+ *
+ * var nodefn = require("when/node/function");
+ *
+ * // Logs '15'
+ * nodefn.apply(onlySmallNumbers, [5]).then(console.log, console.error);
+ *
+ * // Logs 'Calculation failed'
+ * nodefn.apply(onlySmallNumbers, [15]).then(console.log, console.error);
+ *
+ * @param {function} f node-style function that will be called
+ * @param {Array} [args] array of arguments to func
+ * @returns {Promise} promise for the value func passes to its callback
+ */
+ function apply(f, args) {
+ return _apply(f, this, args || []);
+ }
+
+ function dispatch(f, thisArg, args, h) {
+ var cb = createCallback(h);
+ try {
+ switch(args.length) {
+ case 2: f.call(thisArg, args[0], args[1], cb); break;
+ case 1: f.call(thisArg, args[0], cb); break;
+ case 0: f.call(thisArg, cb); break;
+ default:
+ args.push(cb);
+ f.apply(thisArg, args);
+ }
+ } catch(e) {
+ h.reject(e);
+ }
+ }
+
+ /**
+ * Has the same behavior that {@link apply} has, with the difference that the
+ * arguments to the function are provided individually, while {@link apply} accepts
+ * a single array.
+ *
+ * @example
+ * function sumSmallNumbers(x, y, callback) {
+ * var result = x + y;
+ * if(result < 10) {
+ * callback(null, result);
+ * } else {
+ * callback(new Error("Calculation failed"));
+ * }
+ * }
+ *
+ * // Logs '5'
+ * nodefn.call(sumSmallNumbers, 2, 3).then(console.log, console.error);
+ *
+ * // Logs 'Calculation failed'
+ * nodefn.call(sumSmallNumbers, 5, 10).then(console.log, console.error);
+ *
+ * @param {function} f node-style function that will be called
+ * @param {...*} [args] arguments that will be forwarded to the function
+ * @returns {Promise} promise for the value func passes to its callback
+ */
+ function call(f /*, args... */) {
+ return _apply(f, this, slice.call(arguments, 1));
+ }
+
+ /**
+ * Takes a node-style function and returns new function that wraps the
+ * original and, instead of taking a callback, returns a promise. Also, it
+ * knows how to handle promises given as arguments, waiting for their
+ * resolution before executing.
+ *
+ * Upon execution, the orginal function is executed as well. If it passes
+ * a truthy value as the first argument to the callback, it will be
+ * interpreted as an error condition, and the promise will be rejected
+ * with it. Otherwise, the call is considered a resolution, and the promise
+ * is resolved with the callback's second argument.
+ *
+ * @example
+ * var fs = require("fs"), nodefn = require("when/node/function");
+ *
+ * var promiseRead = nodefn.lift(fs.readFile);
+ *
+ * // The promise is resolved with the contents of the file if everything
+ * // goes ok
+ * promiseRead('exists.txt').then(console.log, console.error);
+ *
+ * // And will be rejected if something doesn't work out
+ * // (e.g. the files does not exist)
+ * promiseRead('doesnt_exist.txt').then(console.log, console.error);
+ *
+ *
+ * @param {Function} f node-style function to be lifted
+ * @param {...*} [args] arguments to be prepended for the new function @deprecated
+ * @returns {Function} a promise-returning function
+ */
+ function lift(f /*, args... */) {
+ var args1 = arguments.length > 1 ? slice.call(arguments, 1) : [];
+ return function() {
+ // TODO: Simplify once partialing has been removed
+ var l = args1.length;
+ var al = arguments.length;
+ var args = new Array(al + l);
+ var i;
+ for(i=0; i<l; ++i) {
+ args[i] = args1[i];
+ }
+ for(i=0; i<al; ++i) {
+ args[i+l] = arguments[i];
+ }
+ return _apply(f, this, args);
+ };
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Takes an object that responds to the resolver interface, and returns
+ * a function that will resolve or reject it depending on how it is called.
+ *
+ * @example
+ * function callbackTakingFunction(callback) {
+ * if(somethingWrongHappened) {
+ * callback(error);
+ * } else {
+ * callback(null, interestingValue);
+ * }
+ * }
+ *
+ * var when = require('when'), nodefn = require('when/node/function');
+ *
+ * var deferred = when.defer();
+ * callbackTakingFunction(nodefn.createCallback(deferred.resolver));
+ *
+ * deferred.promise.then(function(interestingValue) {
+ * // Use interestingValue
+ * });
+ *
+ * @param {Resolver} resolver that will be 'attached' to the callback
+ * @returns {Function} a node-style callback function
+ */
+ function createCallback(resolver) {
+ return function(err, value) {
+ if(err) {
+ resolver.reject(err);
+ } else if(arguments.length > 2) {
+ resolver.resolve(slice.call(arguments, 1));
+ } else {
+ resolver.resolve(value);
+ }
+ };
+ }
+
+ /**
+ * Attaches a node-style callback to a promise, ensuring the callback is
+ * called for either fulfillment or rejection. Returns a promise with the same
+ * state as the passed-in promise.
+ *
+ * @example
+ * var deferred = when.defer();
+ *
+ * function callback(err, value) {
+ * // Handle err or use value
+ * }
+ *
+ * bindCallback(deferred.promise, callback);
+ *
+ * deferred.resolve('interesting value');
+ *
+ * @param {Promise} promise The promise to be attached to.
+ * @param {Function} callback The node-style callback to attach.
+ * @returns {Promise} A promise with the same state as the passed-in promise.
+ */
+ function bindCallback(promise, callback) {
+ promise = when(promise);
+
+ if (callback) {
+ promise.then(success, wrapped);
+ }
+
+ return promise;
+
+ function success(value) {
+ wrapped(null, value);
+ }
+
+ function wrapped(err, value) {
+ setTimer(function () {
+ callback(err, value);
+ }, 0);
+ }
+ }
+
+ /**
+ * Takes a node-style callback and returns new function that accepts a
+ * promise, calling the original callback when the promise is either
+ * fulfilled or rejected with the appropriate arguments.
+ *
+ * @example
+ * var deferred = when.defer();
+ *
+ * function callback(err, value) {
+ * // Handle err or use value
+ * }
+ *
+ * var wrapped = liftCallback(callback);
+ *
+ * // `wrapped` can now be passed around at will
+ * wrapped(deferred.promise);
+ *
+ * deferred.resolve('interesting value');
+ *
+ * @param {Function} callback The node-style callback to wrap.
+ * @returns {Function} The lifted, promise-accepting function.
+ */
+ function liftCallback(callback) {
+ return function(promise) {
+ return bindCallback(promise, callback);
+ };
+ }
+});
+
+})(typeof define === 'function' && define.amd ? define : function (factory) { module.exports = factory(require); });
+
+
+