-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinvok.js
100 lines (93 loc) · 3.6 KB
/
invok.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
void function(exports) {
function invok(generatorFunction, that, args) {
return new Promise(function(resolve, reject) {
try {
var ret = generatorFunction.apply(that, args);//执行目标函数
} catch(e) {
return reject(e);
}
if(isGenerator(ret)) {//如果返回generator
runToNextYield(ret);
}
else if(isPromise(ret)) {//如果返回promise
return ret;
}
else {//如果返回普通值
resolve(ret);
}
//执行到下一个yield
function runToNextYield(generator, prevData) {
try {
var yielded = generator.next(prevData);
} catch(e) {
return reject(e);
}
resolveYielded(generator, yielded);
}
//上一次执行遇到的异常,带着异常执行到下一个yield
function runToNextYieldWithException(generator, exception) {
try {
var yielded = generator.throw(exception);
} catch(e) {
return reject(e);
}
resolveYielded(generator, yielded);
}
//处理yield出来的东西
function resolveYielded(generator, yielded) {
if(yielded.done)
return resolve(yielded.value);
if(isPromise(yielded.value)) {
resolvePromise(generator, yielded.value);
}
else if(typeof yielded.value === 'function') {
resolvePromise(generator, invok(yielded.value));
}
else if(isGenerator(yielded.value)) {
runToNextYield(yielded.value)
}
else if(yielded.value instanceof Array) {
resolvePromise(generator, Promise.all(yielded.value));
}
else if(yielded.value.constructor === Object) {
var promises = [], keys = [];
for(var k in yielded.value) {
if(yielded.value.hasOwnProperty(k)) {
keys.push(k);
promises.push(yielded.value[k]);
}
}
resolvePromiseWrap(generator, keys, Promise.all(promises));
}
else {
runToNextYield(generator, yielded.value);
}
}
function resolvePromise(generator, thisPromise) {
thisPromise.then(function(data) {
runToNextYield(generator, data);
}, function(reason) {
runToNextYieldWithException(generator, reason);
});
}
function resolvePromiseWrap(generator, keys, thisPromise) {
thisPromise.then(function(data) {
var wrap = {};
for(var i = 0; i < data.length; i++) {
wrap[keys[i]] = data[i];
}
runToNextYield(generator, wrap);
}, function(reason) {
runToNextYieldWithException(generator, reason);
});
}
});
}
function isPromise(obj) {
return obj && typeof obj.then === 'function';
}
function isGenerator(obj) {
return obj && obj.toString() === '[object Generator]';
}
exports.invok = invok;
}(window);