-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Babel是如何编译async和generator的 #42
Comments
generator函数其实就是维护了一个迭代对象,不停的给这个对象改变状态,直到最后的done。 |
而async函数的关键则是这个函数 function _asyncToGenerator(fn) {
return function() {
var gen = fn.apply(this, arguments);
return new Promise(function(resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
// 注意这里的value 很可能是一个promise
// 而then方法是具有解开promise的功能的
// 自然也可以异步等待这个promise被resolve以后
// 再继续执行下一步
return Promise.resolve(value).then(
function(value) {
step("next", value);
},
function(err) {
step("throw", err);
}
);
}
}
return step("next");
});
};
} |
function* testG() {
// await被编译成了yield
const data = yield getData()
console.log('data: ', data);
const data2 = yield getData()
console.log('data2: ', data2);
return data + '123'
} 假设有这样一个函数,那么其实每次yield都会中止函数,并且外部可以拿到promise 我们就可以在这个promise的then里面,再去把迭代器进一步的调用.next() 这样就可以做到 只有在promise被resolve了以后 迭代器里才会继续前进到下一个yield 其实原理类似于一个generator的autorun,只是支持了promise异步 |
最终版本 /**
* async的执行原理
* 其实就是自动执行generator函数
* 暂时不考虑genertor的编译步骤(更复杂)
*/
const getData = () =>
new Promise(resolve => setTimeout(() => resolve("data"), 1000))
// 这样的一个async函数 应该再1秒后打印data
async function test() {
const data = await getData()
console.log(data)
return data
}
// async函数会被编译成generator函数 (babel会编译成更本质的形态,这里我们直接用generator)
function* testG() {
// await被编译成了yield
const data = yield getData()
console.log('data: ', data);
const data2 = yield getData()
console.log('data2: ', data2);
return data + '123'
}
function asyncToGenerator(generatorFunc) {
return function() {
const gen = generatorFunc.apply(this, arguments)
return new Promise((resolve, reject) => {
function step(key, arg) {
let generatorResult
try {
generatorResult = gen[key](arg)
} catch (error) {
return reject(error)
}
const { value, done } = generatorResult
if (done) {
return resolve(value)
} else {
return Promise.resolve(value).then(
function onResolve(val) {
step("next", val)
},
function onReject(err) {
step("throw", err)
},
)
}
}
step("next")
})
}
}
const testGAsync = asyncToGenerator(testG)
testGAsync().then(result => {
console.log(result)
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
mqyqingfeng/Blog#103
这个系列的两篇
The text was updated successfully, but these errors were encountered: