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());
}