async await
实际上是yield
的语法糖
,当然我们首先得知道async await
是怎么转换成yield
的,
例如:
typescript
async function(){
await Promise.reject(1);
return await Promise.reject(1)
}
实际上转换成的是(以下是简化过的
):
javascript
function a() {
return __awaiter(function* () {
yield Promise.reject(1);
return yield Promise.reject(1);
});
}
a();
__awaiter
实际上就是用yield
实现的async await
语法糖。简单来说,就是用yield
写一个自动执行器
,并且返回一个Promise
对象,Promise
对象的状态由执行过程
的情况而定。
所以我们可以很简单的得出以下代码:
typescript
function __awaiter(fun: GeneratorFunction) {
let resolveFn: (value: unknown) => void;
let rejectFn: (value: unknown) => void;
const generator = fun(); // 执行转换后的generator
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
return promise; // 返回的promise
}
然后我们简单实现一个自动执行器:
typescript
function __awaiter(fun: GeneratorFunction) {
let resolveFn: (value: unknown) => void;
let rejectFn: (value: unknown) => void;
const generator = fun();
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
// 如果yield之后返回的是简单类型,则把它包装成Promise
const adopt = (value: unknown) => {
return value instanceof Promise ? value : Promise.resolve(value);
};
// 自动执行器
const step = (preValue?: unknown) => {
const { value, done } = generator.next(preValue);
adopt(value).then(
nextValue => {
// empty
},
reason => {
// empty
},
);
};
// 执行自动执行器
step();
return promise;
}
但是我们可以看到adopt
后面的then
函数还是空的,这里实际上就是要根据执行状态
来改变Promise
对象的状态。
执行过程中的情况大概分为三种:
1. 执行过程顺利,prmiose
的value
取决于最后一次generator.next()
的值。
所以很简单,我们可以得出如下代码:
typescript
function __awaiter(fun: GeneratorFunction) {
let resolveFn: (value: unknown) => void;
let rejectFn: (value: unknown) => void;
const generator = fun();
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
// 如果yield之后返回的是简单类型,则把它包装成Promise
const adopt = (value: unknown) => {
return value instanceof Promise ? value : Promise.resolve(value);
};
// 自动执行器
const step = (preValue?: unknown) => {
const { value, done } = generator.next(preValue);
adopt(value).then(
nextValue => {
// 执行一切顺利
// 执行一切顺利
// 执行一切顺利
// 执行一切顺利
// 执行一切顺利
if (done) {
resolveFn(nextValue);
} else {
step(nextValue);
}
},
reason => {
// empty
},
);
};
// 执行自动执行器
step();
return promise;
}
2 . 执行过程中出现问题,例如直接throw xxx
,抛出错误,此时需要在next()
外面包裹try{}catch{}
,并且将错误原因赋值给rejectFn
函数,并中断
自动执行器。
从一个yield
到另一个yield
中间发生了错误,这时需要在执行器外层嵌套try{}catch{}
typescript
function __awaiter(fun: GeneratorFunction) {
let resolveFn: (value: unknown) => void;
let rejectFn: (value: unknown) => void;
const generator = fun();
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
const adopt = (value: unknown) => {
return value instanceof Promise ? value : Promise.resolve(value);
};
const step = (preValue?: unknown) => {
// 外层嵌套try catch
// 外层嵌套try catch
// 外层嵌套try catch
// 外层嵌套try catch
// 外层嵌套try catch
// 外层嵌套try cat
try {
const { value, done } = generator.next(preValue);
adopt(value).then(
nextValue => {
if (done) {
resolveFn(nextValue);
} else {
step(nextValue);
}
},
reason => {
// empty
},
);
} catch (e) {
rejectFn(e);
}
};
step();
return promise;
}
3. yield(await)
后面的promise
对象变为reject
状态,并中断自动执行器
。
typescript
function __awaiter(fun: GeneratorFunction) {
let resolveFn: (value: unknown) => void;
let rejectFn: (value: unknown) => void;
const generator = fun();
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
const adopt = (value: unknown) => {
return value instanceof Promise ? value : Promise.resolve(value);
};
const step = (preValue?: unknown) => {
try {
const { value, done } = generator.next(preValue);
adopt(value).then(
nextValue => {
if (done) {
resolveFn(nextValue);
} else {
step(nextValue);
}
},
reason => {
// await 后面的promise变为了reject
// await 后面的promise变为了reject
// await 后面的promise变为了reject
if (done) {
rejectFn(reason);
} else {
step(reason);
}
},
);
} catch (e) {
rejectFn(e);
}
};
step();
return promise;
}
通过以上条件,得到最终代码:
typescript
function __awaiter(fun: GeneratorFunction) {
let resolveFn: (value: unknown) => void;
let rejectFn: (value: unknown) => void;
const generator = fun();
const promise = new Promise((resolve, reject) => {
resolveFn = resolve;
rejectFn = reject;
});
const adopt = (value: unknown) => {
return value instanceof Promise ? value : Promise.resolve(value);
};
const step = (preValue?: unknown) => {
try {
const { value, done } = generator.next(preValue);
adopt(value).then(
nextValue => {
if (done) {
resolveFn(nextValue);
} else {
step(nextValue);
}
},
reason => {
if (done) {
rejectFn(reason);
} else {
step(reason);
}
},
);
} catch (e) {
rejectFn(e);
}
};
step();
return promise;
}