87241940 2019-08-29
Talk is cheap,show you the code
//异步函数1 function doLazy1() { return new Promise((rs, rj) => { setTimeout(() => { console.log('do Lazy1'); rs(); }, 1000) }) } //异步函数2 function doLazy2() { return new Promise((rs, rj) => { setTimeout(() => { console.log('do Lazy2'); rs(); }, 2000) }) } //同步函数 function doNow() { console.log('do now!'); return 'now' } async function doAsync() { console.log('start'); await doLazy1(); console.log('after Lazy1'); await doLazy2(); console.log('after Lazy2'); const res = await doNow(); console.log('after now'); return res; } doAsync(); //打印出: // start // do Lazy1 // after Lazy1 // do Lazy2 // after Lazy2 // do now! // after now // 表达式输出为 // "now" console.log('-----------------'); function runGenerator(generator) { const task = generator(); let lastStep = task.next(); function stepFoward() { if (lastStep.done === false) { return Promise.resolve(lastStep.value).then((res) => { lastStep = task.next(res); return stepFoward(); }) } else { console.log('done') return Promise.resolve(lastStep.value) } } return stepFoward(); } //doAsync被转换成: runGenerator(function* doAsyncFromGenerator() { console.log('start'); yield doLazy1(); console.log('after Lazy1'); yield doLazy2(); console.log('after Lazy2'); const res = yield doNow(); console.log('after now'); return res; }) // doAsync(); //打印出: // start // do Lazy1 // after Lazy1 // do Lazy2 // after Lazy2 // do now! // after now // 表达式输出为 // "now" //babel插件思路 function transportAsyncFunction({ types }) { return { visitor: { FunctionDeclaration(path) { if (path.node.async === true) { path.node.async === false; path.node.generator === true; } //遍历函数内容 path.traverse({AwaitExpression(pathAwait){ //替换AwaitExpression节点为YieldExpression pathAwait.node.type = 'YieldExpression'; }}) //把节点转换为CallExpression //创建runGenerator 把节点转换为CallExpression并把上一步得到的节点当作param //替换上一步得到的节点 types.replaceWith() } } } } //Function构造函数思路 fucntion(target){ //匹配async关键字 const regAsync = //s*async[^{}\(]{1,}(?=function|\()/; //匹配await关键字 const regAwait = /(?<=[/s]+)(await)(?=[/s]+)/g; const regBody = /(?<!{){(.*)}(?!})/; let funcStr = target.toString(); let resultStr = null; resultStr = funcStr.replace(regAsync,' * '); //如果是箭头函数需要转换成普通函数 resultStr = funcStr.replace(/\(([/w]+)\)[/s]*=>/,'function($0)'); //提取参数 const params = funcStr.replace(/\(([/w]*)\)/,'$0').split(','); resultStr = funcStr.replace(regAwait,' yield '); const body = resultStr.replace(regBody,'$1'); //构造出函数 const resultFunction = new Function(...params,body); return runGenerator(resultFunction()); }