Skip to content

Instantly share code, notes, and snippets.

@leizongmin
Last active October 17, 2016 07:27
Show Gist options
  • Save leizongmin/5a72de9fe99aaa429b29ae6b256ed6d7 to your computer and use it in GitHub Desktop.
Save leizongmin/5a72de9fe99aaa429b29ae6b256ed6d7 to your computer and use it in GitHub Desktop.
利用generator与promise实现coroutine
'use strict';
// 检查是否为Promise对象
function isPromise(p) {
return typeof p.then === 'function' && typeof p.catch === 'function';
}
// coroutine包装函数
function cotoutineWrap(genFn) {
const fn = function () {
return new Promise((resolve, reject) => {
const gen = genFn.apply(null, arguments);
function next(value) {
const ret = gen.next(value);
// 如果done=true则表示结束
if (ret.done) return resolve(ret.value);
// 如果是promise则执行
if (isPromise(ret.value)) return ret.value.then(next).catch(reject);
// 其他值则直接跳过
next();
}
// 开始执行
next();
});
};
// 保留函数名和参数信息
const info = genFn.toString().match(/function\s*\*\s*(.*\(.*\))/);
const sign = info && info[1] ? info[1] : '()';
const code = `(function ${sign} { return fn.apply(this, arguments); })`;
return eval(code);
}
// 以下是测试代码 ----------------------------------------------------------------
function sleep(ms) {
return new Promise((resolve, reject) => {
console.log('sleep', ms);
setTimeout(resolve, ms);
// throw new Error('haha');
});
}
cotoutineWrap(function* (n) {
yield n;
for (let i = 0; i < n; i++) {
yield sleep(i * 200);
}
yield n;
return n;
})(5)
.then(ret => console.log('result', ret))
.catch(err => console.log('error', err));
console.log(cotoutineWrap(function* () { yield 123; }).toString());
console.log(cotoutineWrap(function* abc() { yield 123; }).toString());
console.log(cotoutineWrap(function* abc(a, b, c) { yield 123; }).toString());
console.log(cotoutineWrap(function * abc(a, b, c) { yield 123; }).toString());
console.log(cotoutineWrap(function * abc ( a, b, c ) { yield 123; }).toString());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment