消除异步执行器
任务执行的洋葱模型【渡一教育】_哔哩哔哩_bilibili 受该视频启发,实现以下异步执行器:
ts
/** 创建异步运行器 */
export const createAsyncRunner = () => {
const tasks = [];
const add = (task) => {
tasks.push(task);
};
const start = () => {
if (tasks.length > 0) {
_runTask(tasks[0]);
}
};
const _runTask = async (task) => {
try {
await task();
tasks.shift();
if (tasks.length > 0) {
_runTask(tasks[0]);
}
} catch (error) {
console.error(error);
}
};
return {
start,
add,
};
};
可以像如下代码,将所有任务(无论异步还是同步)按照添加顺序依次执行,并且会等待之前的异步任务执行完毕:
ts
/** 异步任务1 */
const asyncTask1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Task 1 completed");
}, 200);
});
};
/** 异步任务2 */
const asyncTask2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Task 2 completed");
}, 100);
});
};
runner.add(asyncTask1);
runner.add(asyncTask2);
runner.start(); // 200ms后完成asyncTask1,再经过100ms完成asyncTask2
这也是js中消除异步的方法之一——将异步任务放到特定的执行环境中进行。
虽然相比写async/await并没有提升多少开发效率,但是考虑可以结合ts的装饰器和类,将实现特定功能的类的异步方法转换成同步,并且使其在特定的执行容器中运行,则可以达到不用写async/await或promise.then()的目的。
端到端测试框架cypress可能使用的也是这样的方案。
但基于这种方案进行异步转同步也有很大的限制,会导致无法很好地和常规js同步代码兼容(必须要在执行器中运行)。