Javascript 如何围绕Web Workers API编写承诺包装器?
我正在写一个利用网络工作者的图书馆。该库的消费者不应该看到任何Web Worker内容,而是应该从该库的公共方法中获得如下承诺:Javascript 如何围绕Web Workers API编写承诺包装器?,javascript,asynchronous,es6-promise,web-worker,Javascript,Asynchronous,Es6 Promise,Web Worker,我正在写一个利用网络工作者的图书馆。该库的消费者不应该看到任何Web Worker内容,而是应该从该库的公共方法中获得如下承诺: // consumer.js const api = new Api(); api.doCalculation(input1).then(data => console.log(data)); api.doCalculation(input2).then(data => console.log(data)); api.doCalculation(inp
// consumer.js
const api = new Api();
api.doCalculation(input1).then(data => console.log(data));
api.doCalculation(input2).then(data => console.log(data));
api.doCalculation(input3).then(data => console.log(data));
在我的库代码中,有一个类包装了Web工作者逻辑。在构造函数中,我创建工作线程并设置“消息”事件侦听器,侦听来自工作线程的传入数据。
在这个类中还有一个doccalculation(input)
方法,它对库的消费者是公开的。它接受输入并将其发送到工作线程以执行实际计算
// api.js
class Api {
constructor() {
this.worker = new Worker('worker.js');
this.worker.addEventListener('message', (e) => {
// I want to return this e.data from the doCalculation method
console.log(e.data);
});
}
doCalculation(input) {
this.worker.postMessage({input: input});
// I want to return a Promise from this method,
// holding the result e.data
}
}
我现在的问题是,如何从持有e.data
的doccalculation
方法返回承诺
我的第一个意图是这样的,这显然不起作用,因为每次调用doccalculation
都会创建一个新的“消息”事件侦听器
// api.js
class Api {
constructor() {
this.worker = new Worker('worker.js');
}
doCalculation(input) {
this.worker.postMessage({input: input});
return new Promise((resolve => {
this.worker.addEventListener('message', (e) => {
resolve(e.data);
});
}))
}
}
这里所有的代码示例都进行了简化,以明确我的观点
我将非常感谢任何关于正确方向的提示 当然,您可以将
resolve
存储在某个地方,例如在对象中:
this.resolvers = {};
this.count = 0; // used later to generate unique ids
然后,对于发送给webworker的每个任务,创建一个唯一的id,并将承诺解析器存储在那里
const id = this.count++;
// Send id and task to WebWorker
return new Promise(resolve => this.resolvers[id] = resolve);
然后,当webworker发送消息时,从中获取id,并解析存储的承诺:
this.resolvers[ id ](data);
delete this.resolvers[id]; // Prevent memory leak
这样一来,(1)您只需要注册一个处理程序,(2)webworker可以同时处理多个任务,(3)您可以通过检查
Object.keys(this.resolvers)
来轻松确定哪些任务正在webworker上运行!非常干净,它的工作非常完美!