用Generator函数和Promise对async/await进行模拟与转换

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

相关推荐