1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | var slice = Array.prototype.slice;
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | module.exports = co['default'] = co.co = co;
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 | co.wrap = function (fn) {
|
27 | createPromise.__generatorFunction__ = fn;
|
28 | return createPromise;
|
29 | function createPromise() {
|
30 | return co.call(this, fn.apply(this, arguments));
|
31 | }
|
32 | };
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | function co(gen) {
|
44 | var ctx = this;
|
45 | var args = slice.call(arguments, 1)
|
46 |
|
47 |
|
48 |
|
49 |
|
50 | return new Promise(function(resolve, reject) {
|
51 | if (typeof gen === 'function') gen = gen.apply(ctx, args);
|
52 | if (!gen || typeof gen.next !== 'function') return resolve(gen);
|
53 |
|
54 | onFulfilled();
|
55 |
|
56 | |
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 | function onFulfilled(res) {
|
63 | var ret;
|
64 | try {
|
65 | ret = gen.next(res);
|
66 | } catch (e) {
|
67 | return reject(e);
|
68 | }
|
69 | next(ret);
|
70 | }
|
71 |
|
72 | |
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | function onRejected(err) {
|
79 | var ret;
|
80 | try {
|
81 | ret = gen.throw(err);
|
82 | } catch (e) {
|
83 | return reject(e);
|
84 | }
|
85 | next(ret);
|
86 | }
|
87 |
|
88 | |
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 | function next(ret) {
|
98 | if (ret.done) return resolve(ret.value);
|
99 | var value = toPromise.call(ctx, ret.value);
|
100 | if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
|
101 | return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
|
102 | + 'but the following object was passed: "' + String(ret.value) + '"'));
|
103 | }
|
104 | });
|
105 | }
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | function toPromise(obj) {
|
116 | if (!obj) return obj;
|
117 | if (isPromise(obj)) return obj;
|
118 | if (isGeneratorFunction(obj) || isGenerator(obj)) return co.call(this, obj);
|
119 | if ('function' == typeof obj) return thunkToPromise.call(this, obj);
|
120 | if (Array.isArray(obj)) return arrayToPromise.call(this, obj);
|
121 | if (isObject(obj)) return objectToPromise.call(this, obj);
|
122 | return obj;
|
123 | }
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 | function thunkToPromise(fn) {
|
134 | var ctx = this;
|
135 | return new Promise(function (resolve, reject) {
|
136 | fn.call(ctx, function (err, res) {
|
137 | if (err) return reject(err);
|
138 | if (arguments.length > 2) res = slice.call(arguments, 1);
|
139 | resolve(res);
|
140 | });
|
141 | });
|
142 | }
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 | function arrayToPromise(obj) {
|
154 | return Promise.all(obj.map(toPromise, this));
|
155 | }
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 | function objectToPromise(obj){
|
167 | var results = new obj.constructor();
|
168 | var keys = Object.keys(obj);
|
169 | var promises = [];
|
170 | for (var i = 0; i < keys.length; i++) {
|
171 | var key = keys[i];
|
172 | var promise = toPromise.call(this, obj[key]);
|
173 | if (promise && isPromise(promise)) defer(promise, key);
|
174 | else results[key] = obj[key];
|
175 | }
|
176 | return Promise.all(promises).then(function () {
|
177 | return results;
|
178 | });
|
179 |
|
180 | function defer(promise, key) {
|
181 |
|
182 | results[key] = undefined;
|
183 | promises.push(promise.then(function (res) {
|
184 | results[key] = res;
|
185 | }));
|
186 | }
|
187 | }
|
188 |
|
189 |
|
190 |
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 | function isPromise(obj) {
|
198 | return 'function' == typeof obj.then;
|
199 | }
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 |
|
209 | function isGenerator(obj) {
|
210 | return 'function' == typeof obj.next && 'function' == typeof obj.throw;
|
211 | }
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 | function isGeneratorFunction(obj) {
|
221 | var constructor = obj.constructor;
|
222 | if (!constructor) return false;
|
223 | if ('GeneratorFunction' === constructor.name || 'GeneratorFunction' === constructor.displayName) return true;
|
224 | return isGenerator(constructor.prototype);
|
225 | }
|
226 |
|
227 | /**
|
228 | * Check for plain object.
|
229 | *
|
230 | * @param {Mixed} val
|
231 | * @return {Boolean}
|
232 | * @api private
|
233 | */
|
234 |
|
235 | function isObject(val) {
|
236 | return Object == val.constructor;
|
237 | }
|