Last active
June 15, 2017 06:31
-
-
Save zyf0330/da21e0591d6d0ea94baaec4b0f6261fa to your computer and use it in GitHub Desktop.
Wrap generator returns promise. Got by myself
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const wrapGenerator = function (Generator) { | |
const promise = new Promise(function (resolve, reject) { | |
const g = Generator() | |
let r = g.next() | |
const nextYield = function (r) { | |
if (r.done == true) { | |
resolve(r.value) | |
return | |
} | |
r.value.then(function (x) { | |
r = g.next(x) | |
nextYield(r) | |
}).catch(function (e) { | |
g.throw(e) | |
}) | |
} | |
nextYield(r) | |
}); | |
return promise | |
} | |
// 转换 Generator 为普通函数 | |
const convertGenerator = function (Generator) { | |
const handleFunc = function (Generator) { | |
const s = Generator.toString() | |
const lines = s.split('\n').slice(1, -1) | |
const appendBrackets = [] | |
for (let i = 0; i < lines.length; i++) { | |
const line = lines[i] | |
const match = line.match(/\s*(?!const|let|var)\s+?([\w0-9_]+?)\s*=\s*yield\s+?(.+)/) | |
if (match == null) { | |
continue | |
} | |
const declare = match[1] | |
const yieldIn = match[2] | |
const yieldFunc = 'yield' | |
lines[i] = `${yieldFunc}(${yieldIn}, function (${declare}) {` | |
appendBrackets.push('})') | |
} | |
const newS = lines.concat(appendBrackets).join('\n') | |
// const newF = new Function(newS) | |
return `(function (){${newS}})` | |
} | |
return function () { | |
// 处理 func,在这里使用 eval 才能使得 g 处于当前作用域 | |
const g = eval(handleFunc(Generator)) | |
// yielding 应该是一个随着 try/catch 层级深入而嵌套的数据结构,才能正确使用生成器 throw 方法 | |
// 此处简单看作没有 try/catch 的情形 | |
let yielding = {in: undefined, out: g}; | |
const yield = function (yieldInValue, yieldOutCb) { | |
yielding = { | |
in: yieldInValue, | |
out: yieldOutCb | |
} | |
} | |
g.next = function (value) { | |
const yieldOutCb = yielding.out | |
yielding = null | |
const returnValue = yieldOutCb(value) | |
const done = yielding == null | |
return { | |
value: done ? returnValue : yielding.in, | |
done: done | |
} | |
} | |
return g | |
} | |
} | |
const fetch1 = function (g) { | |
return Promise.resolve('fetch1') | |
} | |
const fetch2 = function (g) { | |
return Promise.resolve('fetch2') | |
} | |
const Generator = function *() { | |
console.log('before first yield statement') | |
const u1 = yield fetch1() | |
const u2 = yield fetch2() | |
console.log('inner done', 'u1', u1, 'u2', u2) | |
return 'outer done' | |
} | |
console.log('origin Generator') | |
wrapGenerator(Generator).then(function (x) { | |
console.log(x, '\n') | |
console.log('converted ....') | |
wrapGenerator(convertGenerator(Generator)).then(function (x) { | |
console.log(x) | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
添加将 Generator 转换为普通函数。
这里只考虑简单的单一作用域代码块,因此也不考虑异常捕获。