我有一个类,它管理一个函数队列并提供一个简单的 API manager.queue({data: foo}, function, callback)
,然后在我的渲染器进程中单击一个按钮,我调用它来对各种预定义函数进行排队,但这里的问题是最后一个函数可以使用来自第一个功能。
我最初尝试的是:
起初我将返回数据存储在results: any[] = []
回调中的一个变量中,然后当我想将第二个任务排队时,我会简单地manager.queue({data: results[0], function2, callback);
.
现在,显然这不起作用,因为 JavaScript 是按值传递的,并且result[0]
是在队列时传递的,而不是在函数执行时从数组中读取值。
当前实现:
目前我延迟排队,直到排队功能完成。即我创建了一组任务,它们调用manager.queue....
而不是直接排队,然后在我的回调函数中tasks.shift()() //which adds a the function to queue
,await manager.start()
因为管理器的队列中总是只有一个项目,所以它停止,执行回调,然后将另一个函数添加到队列并重新启动管理器使函数出队。
问题:这工作正常,但它破坏了管理器类的观点,调用类不应该跟踪任务和结果,而只需将任务排队并让管理器使用第二个成功的结果功能。
现在理论足够了,是时候写一些代码了:)
Manager.ts
interface TaskFunctionArguments<JobData>
{
data: JobData
};
export type TaskFunction<JobData, ReturnData> = (
arg: TaskFunctionArguments<JobData>
) => Promise<ReturnData>;
export default class Manager<JobData = any, ReturnData = any>
{
private jobQueue: Queue<Job<JobData, ReturnData>> = new Queue<Job<JobData, ReturnData>>();
public queue(data: JobData, task: TaskFunction<JobData, ReturnData>, callbacks?: ExecuteCallbacks)
{
const job = new Job<JobData, ReturnData>(data, task, callbacks);
this.jobQueue.push(job);
}
public async start()
{
let job;
let result: any;
let errorState: Error | null = null;
while (this.jobQueue.size())
{
job = this.jobQueue.shift();
try
{
result = await job.taskFunction({ data: job.data as JobData });
}
catch (err)
{
errorState = err;
}
if (errorState)
{
job.executeCallbacks.reject(errorState || new Error("asf"));
return { type: "error", error: errorState || new Error("asf") };
}
else
{
job.executeCallbacks.resolve(result);
// return { type: "success", data: result };
}
}
return { type: "success", data: result };
}
}
代码是从中获得灵感/复制的,puppeteer-cluster
因为如果我编写了相同的代码,那将是一团糟:P,我想在打字稿中学习泛型。
当前实现调用者代码
var tasks: ((value?: any) => void)[] = [];
var results: any[] = [];
//callback code
async (r) =>
{
results.push(r);
if (tasks.length)
{
tasks.shift()();
let result = await manager.start();
console.log("result: ", result);
}
}
//when I click want to add a function
tasks.push(() =>
{
manager.queue({data:foo}, function, callback);
};
//to queue the second task
tasks.push(() =>
{
//mostly result[0] is parsed like: result[0] as MyInterface
manager.queue({data: results[0]}, function2, callback});
};
//When I want to start the queue
tasks.shift()();
await manager.start();