UNPKG

3.27 kBJavaScriptView Raw
1'use strict';
2
3// This file contains then/promise specific extensions that are only useful
4// for node.js interop
5
6var Promise = require('./core.js');
7
8
9module.exports = Promise;
10
11/* Static Functions */
12
13Promise.denodeify = function (fn, argumentCount) {
14 if (
15 typeof argumentCount === 'number' && argumentCount !== Infinity
16 ) {
17 return denodeifyWithCount(fn, argumentCount);
18 } else {
19 return denodeifyWithoutCount(fn);
20 }
21};
22
23var callbackFn = (
24 'function (err, res) {' +
25 'if (err) { rj(err); } else { rs(res); }' +
26 '}'
27);
28function denodeifyWithCount(fn, argumentCount) {
29 var args = [];
30 for (var i = 0; i < argumentCount; i++) {
31 args.push('a' + i);
32 }
33 var body = [
34 'return function (' + args.join(',') + ') {',
35 'var self = this;',
36 'return new Promise(function (rs, rj) {',
37 'var res = fn.call(',
38 ['self'].concat(args).concat([callbackFn]).join(','),
39 ');',
40 'if (res &&',
41 '(typeof res === "object" || typeof res === "function") &&',
42 'typeof res.then === "function"',
43 ') {rs(res);}',
44 '});',
45 '};'
46 ].join('');
47 return Function(['Promise', 'fn'], body)(Promise, fn);
48}
49function denodeifyWithoutCount(fn) {
50 var fnLength = Math.max(fn.length - 1, 3);
51 var args = [];
52 for (var i = 0; i < fnLength; i++) {
53 args.push('a' + i);
54 }
55 var body = [
56 'return function (' + args.join(',') + ') {',
57 'var self = this;',
58 'var args;',
59 'var argLength = arguments.length;',
60 'if (arguments.length > ' + fnLength + ') {',
61 'args = new Array(arguments.length + 1);',
62 'for (var i = 0; i < arguments.length; i++) {',
63 'args[i] = arguments[i];',
64 '}',
65 '}',
66 'return new Promise(function (rs, rj) {',
67 'var cb = ' + callbackFn + ';',
68 'var res;',
69 'switch (argLength) {',
70 args.concat(['extra']).map(function (_, index) {
71 return (
72 'case ' + (index) + ':' +
73 'res = fn.call(' + ['self'].concat(args.slice(0, index)).concat('cb').join(',') + ');' +
74 'break;'
75 );
76 }).join(''),
77 'default:',
78 'args[argLength] = cb;',
79 'res = fn.apply(self, args);',
80 '}',
81
82 'if (res &&',
83 '(typeof res === "object" || typeof res === "function") &&',
84 'typeof res.then === "function"',
85 ') {rs(res);}',
86 '});',
87 '};'
88 ].join('');
89
90 return Function(
91 ['Promise', 'fn'],
92 body
93 )(Promise, fn);
94}
95
96Promise.nodeify = function (fn) {
97 return function () {
98 var args = Array.prototype.slice.call(arguments);
99 var callback =
100 typeof args[args.length - 1] === 'function' ? args.pop() : null;
101 var ctx = this;
102 try {
103 return fn.apply(this, arguments).nodeify(callback, ctx);
104 } catch (ex) {
105 if (callback === null || typeof callback == 'undefined') {
106 return new Promise(function (resolve, reject) {
107 reject(ex);
108 });
109 } else {
110 setImmediate(function () {
111 callback.call(ctx, ex);
112 })
113 }
114 }
115 }
116};
117
118Promise.prototype.nodeify = function (callback, ctx) {
119 if (typeof callback != 'function') return this;
120
121 this.then(function (value) {
122 setImmediate(function () {
123 callback.call(ctx, null, value);
124 });
125 }, function (err) {
126 setImmediate(function () {
127 callback.call(ctx, err);
128 });
129 });
130};