You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
130 lines
3.2 KiB
130 lines
3.2 KiB
'use strict'; |
|
|
|
// This file contains then/promise specific extensions that are only useful |
|
// for node.js interop |
|
|
|
var Promise = require('./core.js'); |
|
|
|
|
|
module.exports = Promise; |
|
|
|
/* Static Functions */ |
|
|
|
Promise.denodeify = function (fn, argumentCount) { |
|
if ( |
|
typeof argumentCount === 'number' && argumentCount !== Infinity |
|
) { |
|
return denodeifyWithCount(fn, argumentCount); |
|
} else { |
|
return denodeifyWithoutCount(fn); |
|
} |
|
}; |
|
|
|
var callbackFn = ( |
|
'function (err, res) {' + |
|
'if (err) { rj(err); } else { rs(res); }' + |
|
'}' |
|
); |
|
function denodeifyWithCount(fn, argumentCount) { |
|
var args = []; |
|
for (var i = 0; i < argumentCount; i++) { |
|
args.push('a' + i); |
|
} |
|
var body = [ |
|
'return function (' + args.join(',') + ') {', |
|
'var self = this;', |
|
'return new Promise(function (rs, rj) {', |
|
'var res = fn.call(', |
|
['self'].concat(args).concat([callbackFn]).join(','), |
|
');', |
|
'if (res &&', |
|
'(typeof res === "object" || typeof res === "function") &&', |
|
'typeof res.then === "function"', |
|
') {rs(res);}', |
|
'});', |
|
'};' |
|
].join(''); |
|
return Function(['Promise', 'fn'], body)(Promise, fn); |
|
} |
|
function denodeifyWithoutCount(fn) { |
|
var fnLength = Math.max(fn.length - 1, 3); |
|
var args = []; |
|
for (var i = 0; i < fnLength; i++) { |
|
args.push('a' + i); |
|
} |
|
var body = [ |
|
'return function (' + args.join(',') + ') {', |
|
'var self = this;', |
|
'var args;', |
|
'var argLength = arguments.length;', |
|
'if (arguments.length > ' + fnLength + ') {', |
|
'args = new Array(arguments.length + 1);', |
|
'for (var i = 0; i < arguments.length; i++) {', |
|
'args[i] = arguments[i];', |
|
'}', |
|
'}', |
|
'return new Promise(function (rs, rj) {', |
|
'var cb = ' + callbackFn + ';', |
|
'var res;', |
|
'switch (argLength) {', |
|
args.concat(['extra']).map(function (_, index) { |
|
return ( |
|
'case ' + (index) + ':' + |
|
'res = fn.call(' + ['self'].concat(args.slice(0, index)).concat('cb').join(',') + ');' + |
|
'break;' |
|
); |
|
}).join(''), |
|
'default:', |
|
'args[argLength] = cb;', |
|
'res = fn.apply(self, args);', |
|
'}', |
|
|
|
'if (res &&', |
|
'(typeof res === "object" || typeof res === "function") &&', |
|
'typeof res.then === "function"', |
|
') {rs(res);}', |
|
'});', |
|
'};' |
|
].join(''); |
|
|
|
return Function( |
|
['Promise', 'fn'], |
|
body |
|
)(Promise, fn); |
|
} |
|
|
|
Promise.nodeify = function (fn) { |
|
return function () { |
|
var args = Array.prototype.slice.call(arguments); |
|
var callback = |
|
typeof args[args.length - 1] === 'function' ? args.pop() : null; |
|
var ctx = this; |
|
try { |
|
return fn.apply(this, arguments).nodeify(callback, ctx); |
|
} catch (ex) { |
|
if (callback === null || typeof callback == 'undefined') { |
|
return new Promise(function (resolve, reject) { |
|
reject(ex); |
|
}); |
|
} else { |
|
setImmediate(function () { |
|
callback.call(ctx, ex); |
|
}) |
|
} |
|
} |
|
} |
|
}; |
|
|
|
Promise.prototype.nodeify = function (callback, ctx) { |
|
if (typeof callback != 'function') return this; |
|
|
|
this.then(function (value) { |
|
setImmediate(function () { |
|
callback.call(ctx, null, value); |
|
}); |
|
}, function (err) { |
|
setImmediate(function () { |
|
callback.call(ctx, err); |
|
}); |
|
}); |
|
};
|
|
|