我有一个MethodQueue类,它将方法排入队列数组并执行它们。这里的棘手部分是,我想一次执行一个作业,下一个作业必须在前一个完成后的x秒后开始,以避免在任何时间内超过请求。
所以我就这样实现了MethodQueue类。
class MethodQueue {
private queue: (() => Promise<any>)[] = [];
private isExecuting = false;
async enqueue(method: () => Promise<any>): Promise<void> {
this.queue.push(method);
if (!this.isExecuting) {
this.executeNext();
}
}
private async executeNext(): Promise<void> {
if (this.isExecuting) return;
this.isExecuting = true;
const method = this.queue.shift();
if (method) {
await method();
this.isExecuting = false;
setTimeout(() => this.executeNext(), 1000);
} else {
this.isExecuting = false;
}
}
}
我有一个SendQueue类,其中包含我从其他文件中使用的静态方法。
export class SendQueue {
private static methodQueue = new MethodQueue();
public static async m1(param1: string, param2: number): Promise<string> {
return new Promise<string>((resolve) => {
SendQueue.methodQueue.enqueue(async () => {
const result = await Send.m1(param1, param2);
resolve(result);
});
});
}
public static async m2(param1: string): Promise<string> {
return new Promise<string>((resolve) => {
SendQueue.methodQueue.enqueue(async () => {
const result = await Send.m2(param1);
resolve(result);
});
});
}
public static async m3(param1: string, param2: boolean): Promise<string> {
return new Promise<string>((resolve) => {
SendQueue.methodQueue.enqueue(async () => {
const result = await Send.m3(param1, param2);
resolve(result);
});
});
}
}
最后我有Send类,它有实际的代码
class Send {
public static async m1(param1: string, _param2: number): Promise<string> {
console.log(`Done ${param1}: ${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()}:${new Date().getMilliseconds()}`);
return "result from m1";
}
public static async m2(param1: string): Promise<string> {
console.log(`Done ${param1}: ${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()}:${new Date().getMilliseconds()}`);
return "result from m2";
}
public static async m3(param1: string, _param3: boolean): Promise<string> {
console.log(`Done ${param1}: ${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()}:${new Date().getMilliseconds()}`);
return "result from m3";
}
}
当我执行多个请求时,它的命中和未命中与调用之间的多个等待
(async () => {
SendQueue.m1("m1", 1);
SendQueue.m2("m2");
SendQueue.m3("m3", true);
await new Promise((resolve) => setTimeout(resolve, 1000));
SendQueue.m1("m4", 1);
await new Promise((resolve) => setTimeout(resolve, 2000));
SendQueue.m2("m5");
await new Promise((resolve) => setTimeout(resolve, 2500));
SendQueue.m3("m6", true);
await new Promise((resolve) => setTimeout(resolve, 1000));
SendQueue.m1("m7", 1);
SendQueue.m2("m8");
SendQueue.m3("m9", true);
await new Promise((resolve) => setTimeout(resolve, 13000));
SendQueue.m1("m10", 1);
await new Promise((resolve) => setTimeout(resolve, 1000));
SendQueue.m2("m11");
SendQueue.m3("m12", true);
await new Promise((resolve) => setTimeout(resolve, 1000));
SendQueue.m1("m13", 1);
})();
输出:
我的代码有什么问题?
1条答案
按热度按时间k3bvogb11#
我看到了一些潜在的问题。
首先,在
await method();
周围没有try/catch
。因此,如果该方法拒绝,您将永远不会将this.isExecuting = false;
设置回false,并且您将不会调度队列中的下一个方法。第二,执行
setTimeout()
,但如果在计时器触发之前,其他代码调用了enqueue()
,那么它将在计时器触发之前调用executeNext()
,然后计时器将触发并再次调用它。似乎executeNext()
需要知道计时器何时已经在运行,并且在计时器触发之前不执行任何操作。以下是针对这些问题的建议修复方法(注意,我不是TypeScript人员,因此您可能需要为新的
timer
示例变量分配类型):