Skip to content

Commit a3f10af

Browse files
author
Aa2212002
committed
co
1 parent 8f56793 commit a3f10af

File tree

5 files changed

+190
-2
lines changed

5 files changed

+190
-2
lines changed

co/1.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
11111

co/2.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
22222

co/index.js

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
const slice = Array.prototype.slice;
2+
function isObject(val) {
3+
return Object === val.constructor;
4+
}
5+
6+
function isPromise(obj) {
7+
return typeof obj.then === "function";
8+
}
9+
10+
function isGenertor(obj) {
11+
return typeof obj.next === "function" && typeof obj.return === "function" && typeof obj.throw === "function";
12+
}
13+
14+
function isGenertorFunction(fn) {
15+
try {
16+
const constructor = fn.constructor;
17+
if (!constructor) {
18+
return false;
19+
}
20+
if (constructor.name === "GeneratorFunction") {
21+
return true;
22+
}
23+
return isGenertor(constructor.prototype);
24+
} catch (e) {
25+
return false;
26+
}
27+
}
28+
29+
/**
30+
* @param {*} thunk -> 将参数与回调函数分离 fn(p1, p2, cb) -> thunk(p1, p2)(cb)
31+
*/
32+
function thunkToPromise(thunk) {
33+
const ctx = this;
34+
return new Promise((resolve, reject) => {
35+
thunk.call(ctx, (err, res) => {
36+
if (err) return reject(err);
37+
if (arguments.length > 2) {
38+
res = slice.call(arguments, 1);
39+
}
40+
resolve(res);
41+
})
42+
})
43+
}
44+
45+
function objectToPromise(obj) {
46+
const results = new obj.constructor();
47+
const keys = Reflect.ownKeys(obj);
48+
const promises = [];
49+
for(let i = 0; i < keys.length; i++) {
50+
const key = keys[i];
51+
const promise = toPromise.call(this, obj[key]);
52+
if(promise && isPromise(promise)) {
53+
defer(promise, key)
54+
} else {
55+
results[key] = obj[key]
56+
}
57+
}
58+
return Promise.all(promises).then(() => results);
59+
function defer(promise, key) {
60+
results[key] = undefined;
61+
promises.push(promise.then(res => {
62+
results[key] = res;
63+
}))
64+
}
65+
}
66+
67+
function arrayToPromise(arr) {
68+
return Promise.all(arr.map(toPromise, this))
69+
}
70+
71+
function toPromise(obj) {
72+
if(!obj) return obj;
73+
if(isPromise(obj)) return obj;
74+
if(isGenertor(obj) || isGenertorFunction(obj)) return co.call(this, obj);
75+
if(typeof obj === "function") return thunkToPromise.call(this, obj);
76+
if(Array.isArray(obj)) return arrayToPromise.call(this, obj);
77+
if(isObject(obj)) return objectToPromise.call(this, obj);
78+
return obj;
79+
}
80+
81+
function co(gen) {
82+
const ctx = this;
83+
const args = slice.call(arguments, 1);
84+
let it;
85+
return new Promise((resolve, reject) => {
86+
if(typeof gen === "function") {
87+
it = gen.apply(ctx, args);
88+
}
89+
if(!it || !isGenertor(it)) {
90+
return resolve(it)
91+
}
92+
onFulfilled();
93+
function onFulfilled(res) {
94+
let ret;
95+
try {
96+
ret = it.next(res)
97+
} catch(e) {
98+
return reject(e)
99+
}
100+
next(ret)
101+
}
102+
function onRejected(err) {
103+
let ret;
104+
try {
105+
ret = it.throw(err)
106+
} catch (e) {
107+
return reject(e)
108+
}
109+
next(ret)
110+
}
111+
function next(ret) {
112+
if(ret.done) return resolve(ret.value);
113+
const value = toPromise.call(ctx, ret.value);
114+
if(value && isPromise(value)) {
115+
return value.then(onFulfilled, onRejected)
116+
}
117+
return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' +
118+
'but the following object was passed: "' + String(ret.value) + '"'));
119+
}
120+
})
121+
}
122+
co.wrap = function (fn) {
123+
createPromise.__generatorFunction__ = fn;
124+
return createPromise;
125+
function createPromise() {
126+
return co.call(this, fn.apply(this, arguments));
127+
}
128+
};
129+
const fs = require("fs");
130+
const path = require('path');
131+
const readFile = function (filePath) {
132+
return new Promise((resolve, reject) => {
133+
fs.readFile(filePath, "utf-8", (err, data) => {
134+
if (!err) {
135+
resolve(data);
136+
} else {
137+
reject(err)
138+
}
139+
})
140+
})
141+
};
142+
143+
function* generator() {
144+
const file1 = yield readFile(path.join(__dirname, '1.txt'));
145+
console.log(file1);
146+
const file2 = yield readFile(path.join(__dirname, '2.txt'));
147+
console.log(file2);
148+
const file3 = yield readFile(path.join(__dirname, '1.txt'));
149+
console.log(file3);
150+
const file4 = yield readFile(path.join(__dirname, '2.txt'));
151+
console.log(file4);
152+
const file5 = yield readFile(path.join(__dirname, '1.txt'));
153+
console.log(file5);
154+
return 666;
155+
}
156+
co(generator);

promise.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,13 @@ function runGen(gen) {
3737
};
3838
next();
3939
};
40-
runGen(generator)
40+
runGen(generator);
41+
42+
43+
function* gen() {
44+
const a = yield 4;
45+
console.log(a);
46+
}
47+
const it = gen();
48+
console.log(it.next());
49+
it.next(3)

simple.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,21 @@ run(generator)
4545
// });
4646
// });
4747

48-
48+
function thunk(fn) {
49+
return function() {
50+
const args = Array.prototype.slice.call(arguments);
51+
const ctx = this;
52+
return function(cb) {
53+
let called = false;
54+
args.push(function() {
55+
if(called) return;
56+
called = true;
57+
cb.apply(ctx, arguments)
58+
});
59+
return fn.apply(ctx, args);
60+
}
61+
}
62+
}
4963

5064

5165
const Thunk = function (fn) {
@@ -67,3 +81,10 @@ function test(name, age, callback) {
6781
};
6882
const testThunk = Thunk(test);
6983
testThunk(1,2)((a, b) => console.log(a, b))
84+
var obj = {
85+
a: [1, 2, 3]
86+
};
87+
var c = obj.a;
88+
const v = {};
89+
v.c = c;
90+
console.log(obj.a === v.c)

0 commit comments

Comments
 (0)