-
Notifications
You must be signed in to change notification settings - Fork 634
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
阿里&字节:手写 async/await 的实现 #56
Comments
之前看过一篇不错的,看看顺便默写下代码 function asyncToGen(genFunction) {
return function (...args) {
const gen = genFunction.apply(this, args);
return new Promise((resolve, reject) => {
function step(key, arg) {
let genResult;
try {
genResult = gen[key](arg);
} catch (err) {
return reject(err);
}
const { value, done } = genResult;
if (done) {
return resolve(value);
}
return Promise.resolve(value).then(
(val) => {
step('next', val);
},
(err) => {
step('throw', err);
},
);
}
step('next');
});
};
}
const getData = () => new Promise(resolve => setTimeout(() => resolve('data'), 1000));
function* testG() {
const data = yield getData();
console.log('data: ', data);
const data2 = yield getData();
console.log('data2: ', data2);
return 'success';
}
const gen = asyncToGen(testG);
gen().then(res => console.log(res)); |
本质是希望实现一个co函数 let delay = function (time, fnc) {
setTimeout(() => {
fnc(time);
}, time);
}
let promisefy = (fn) => {
return (...arg) => {
return new Promise ((resolve, reject)=> {
fn(...arg, (param)=>{
resolve(param);
})
});
}
}
let delayP = promisefy(delay);
const gen = function* () {
const ret1 = yield delayP(1000);
console.log(ret1);
const ret2 = yield delayP(2000);
console.log(ret2);
}
// 阴间写法
const g = gen();
g.next().value.then((res1)=>{
g.next(res1).value.then((res2)=>{
//
});
})
// 正常写法
function co (generator) {
return new Promise((resolve, reject)=>{
const gen = generator();
function next (...param) {
let tmp = gen.next(...param);
if (tmp.done) {
resolve(tmp.value);
return;
}
tmp.value.then((...ret)=>{
next(...ret);
})
}
next();
})
}
co(gen).then((res)=>{
console.log(res);
}) |
function fn(nums) {
//返回一个Promise对象 因为async 就是返回Promise对象
return new Promise((resolve) => {
setTimeout(() => {
resolve(nums * 2)
}, 1000)
})
}
function* generator() {
const num1 = yield fn(1)
const num2 = yield fn(num1)
const num3 = yield fn(num2)
return num3
}
function generatorToAsync2(generator) {
return function() {
const gen = generator.apply(this,arguments)
return new Promise((resolve,reject)=>{
function _next(key,arg) {
let res
try {
res = gen[key](arg)
const {value,done} = res
if(done) {
return resolve(value)
} else {
return Promise.resolve(value).then(val=>_next('next',val),error=>_next('throw',error))
}
} catch(error) {
return reject(error)
}
}
_next('next')
})
}
}
const asyncFn2 = generatorToAsync2(generator)
asyncFn2().then(res=>console.log(res)) |
基于前面的测试用例实现一个简单版的(代码可以复制运行)
/**
* async的实现
* @author waldon
* @param {*} generatorFn - 生成器函数
*/
function asyncWrapper(generatorFn) {
const g = generatorFn()
return new Promise((resolve, reject) => {
function autoNext(g, nextVal) {
const { value, done } = g.next(nextVal)
if (!done) {
value.then((res) => {
autoNext(g, res)
})
} else {
resolve(value)
}
}
autoNext(g)
})
}
// 测试
const getData = () => new Promise((resolve) => setTimeout(() => resolve('data'), 1000))
function* testG() {
const data = yield getData()
console.log('data: ', data)
const data2 = yield getData()
console.log('data2: ', data2)
return 'success'
}
asyncWrapper(testG).then((res) => {
console.log(res)
})
// 期望顺序输出 data data2 success |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Async是如何被 JavaScript 实现的
await 内部实现了 generator,其实 await 就是 generator 加上 Promise的语法糖,且内部实现了自动执行 generator。如果你熟悉 co 的话,其实自己就可以实现这样的语法糖。
The text was updated successfully, but these errors were encountered: