这个很好用,我们要写一个类似的方法,asyncFunction,至于await完全是添头。
Promise和generator方法
经常有人说其实async就是generator的语法糖,也用来弥补它的一些不足之处,所以来尝试下,如何使用generator实现async,看看原理 我们先写一个简单的promise生成器作为异步函数
javascript
const delayer = t => new Promise(resolve => setTimeout(resolve, t))
我们来看看如果使用async,怎么转换为同步
javascript
async function count(){
await delayer(1000);
console.log(1);
await delayer(1000);
console.log(1);
await delayer(1000);
console.log(1);
}
// 执行count的结果是每隔一秒打印一个1
关于generator的一些方法和使用这边就不做过多介绍了,想要看的同学可以找度娘或者点击文章下方的参考文档。 接下来就是开始实现的阶段了,其实我们要做的是把generator从手动执行变成自动执行,也就是自动next到底,获得预期的返回。 我们先定义一个generator函数
javascript
function* genFunction(){
console.log(2);
const d1 = yield delayer(1000);
console.log(22);
const d2 = yield delayer(1000);
console.log(222);
const d3 = yield delayer(1000);
console.log(2222);
return 'result'
}
接下来就是自动化函数执行阶段了
javascript
function asynction(genFunction, ...args){
const genFun = genFunction(...args)
// 设置执行函数
function next(data) {
return new Promise((resolve, reject) => {
const {value, result} = genFun.next(data)
if (done) return
value.then(data => next(data)).catch(e => reject(e))
})
}
return next()
}
这个方案看起来不是那么正常,看下一个
其他方案
其实差不多
typescript
// 现在有一个方法
var a = 1;
const delay = () => {
return new Promise((resv) => setTimeout(() => resv(a++), 1000));
};
const fn = () => {
console.log("1");
delay();
console.log("2");
delay();
console.log("3");
delay();
};
// 看得出是异步的,可能会同时输出1,我们想让他们变同步
// 使用sync来执行
const fn1 = async () => {
console.log("1");
await delay();
console.log("2");
await delay();
console.log("3");
await delay();
};
// 自己搞一个async实现这个东西,首先使用generator试试
function* fn2(cc) {
console.log("1");
yield delay();
console.log("2");
yield delay();
console.log("3");
yield delay();
return 555;
}
// 如果做个自动化next,也就完成了await的作用了,那么需要的是什么,是回调!
// 一直执行,直到next的done = true
function run(gFun, ...initValues) {
let gen = gFun(...initValues);
function next() {
return new Promise((resolve, reject) => {
let result = gen.next();
if (result.done) return;
result.value.then(() => next()).catch((e) => reject(e));
});
}
return next();
}
// run(fn2).catch((err) => console.log(err));
function run2(gFun, ...initValues) {
let gen = gFun(...initValues);
return new Promise((res, rej) => {
let result;
const next = (...args) => {
console.log("args", args);
result = gen.next(...args);
if (result.done) {
console.log("xxx", result.value);
return res(result.value);
}
return result.value.then((res) => {
console.log("yyy", result.value, res);
return next(222);
});
};
return next(2);
});
}
async function kk() {
console.log(await run2(fn2));
}
kk();