热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

Talkischeap,showyouthecode异步函数1functiondoLazy1(){returnnewPromise((rs,rj){setTimeout((){

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

推荐阅读
author-avatar
木色雪魂K
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有