用Generator函數和Promise對async/await進行模擬與轉換

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章