Talk is cheap,show you the codenode
//異步函數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()); }