59 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			59 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | // freeze Array#slice, just in case of funny business later.
 | ||
|  | var _slice = Array.prototype.slice; | ||
|  | var getPromise = require('./_promise.js'); | ||
|  | 
 | ||
|  | // deferred gets its own scope to prevent inadvertent capture in the closure
 | ||
|  | var deferred = function(options) { | ||
|  |     var Promise = getPromise(); | ||
|  |     var resolve, reject, p = new Promise(function(_resolve, _reject) { | ||
|  |         resolve = _resolve; reject = _reject; | ||
|  |     }); | ||
|  |     var pattern = (options && options.pattern); | ||
|  |     var noError = (options && options.noError); | ||
|  |     var cb = pattern ? function(err) { | ||
|  |         if (err && !noError) { return reject(err); } | ||
|  |         var result = {}, i, offset = noError ? 0 : 1; | ||
|  |         for (i = 0; i < pattern.length; i++) { | ||
|  |             result[pattern[i]] = arguments[i+offset]; | ||
|  |         } | ||
|  |         resolve(result); | ||
|  |     } : noError ? resolve : function(err, val) { | ||
|  |         if (err) { reject(err); } else { resolve(val); } | ||
|  |     }; | ||
|  |     return { promise: p, callback: cb }; | ||
|  | }; | ||
|  | var promisify = module.exports = function(context, func, mandatoryArgs, options) { | ||
|  |     if (options && options.callbackIsFirstArg) { | ||
|  |         // duplicate some code here so we don't have to process this unusual
 | ||
|  |         // situation at runtime in the common case.
 | ||
|  |         return function(cb) { | ||
|  |             if (typeof(cb) === 'function') { | ||
|  |                 return func.apply(context, arguments); | ||
|  |             } | ||
|  |             var d = deferred(options); | ||
|  |             var a = _slice.call(arguments, 0); | ||
|  |             a.unshift(d.callback); | ||
|  |             func.apply(context, a); | ||
|  |             return d.promise; | ||
|  |         }; | ||
|  |     } | ||
|  |     return function() { | ||
|  |         var cb = arguments[arguments.length - 1]; | ||
|  |         if (typeof(cb) === 'function') { | ||
|  |             return func.apply(context, arguments); | ||
|  |         } | ||
|  |         // ooh, promises.
 | ||
|  |         var d = deferred(options); | ||
|  |         var a = _slice.call(arguments, 0); | ||
|  |         while (a.length < mandatoryArgs) { a.push(undefined); } | ||
|  |         a.push(d.callback); | ||
|  |         var retval = func.apply(context, a); | ||
|  |         if (options && options.returnsObject) { | ||
|  |             // it would be nice to have a better convention here
 | ||
|  |             Object.defineProperty(retval, 'promise', { value: d.promise }); | ||
|  |             return retval; | ||
|  |         } | ||
|  |         return d.promise; | ||
|  |     }; | ||
|  | }; |