Ben*_*158 2 javascript asynchronous web-worker es6-promise
I am writing a library which makes use of Web Workers. The consumer of the library should not see any of the Web Worker stuff and should instead get returned a Promise from the public methods of this library like this:
// 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));
Run Code Online (Sandbox Code Playgroud)
In my library code I have a class which wraps the Web Worker logic. In the constructor I create the worker and set the "message" event listener, listening for incoming data from the worker thread.
Also in this class there is a doCalculation(input) method which is public to the consumer of the library. It takes the input and sends it to the worker thread to perform the actual calculation.
// 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
}
}
Run Code Online (Sandbox Code Playgroud)
My question now is, how can I return a Promise from the doCalculation method holding e.data?
My first intend was something like this which obviously doesn't work because a new "message" event listener is created with every call to doCalculation.
// 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);
});
}))
}
}
Run Code Online (Sandbox Code Playgroud)
All the code examples here are simplified to only make my point clear.
I would be thankful for any hints into the right direction!
For sure you could store resolve somewhere, e.g. in an object:
this.resolvers = {};
this.count = 0; // used later to generate unique ids
Run Code Online (Sandbox Code Playgroud)
Then for each task sent to the webworker, create a unique id, and store the promise resolver there
const id = this.count++;
// Send id and task to WebWorker
return new Promise(resolve => this.resolvers[id] = resolve);
Run Code Online (Sandbox Code Playgroud)
Then when the webworker sends a message, get the id from it, and resolve the stored promise:
this.resolvers[ id ](data);
delete this.resolvers[id]; // Prevent memory leak
Run Code Online (Sandbox Code Playgroud)
这样 (1) 您只需要注册一个处理程序,(2) webworker 可以同时处理多个任务,以及 (3) 您可以通过检查Object.keys(this.resolvers).
| 归档时间: |
|
| 查看次数: |
708 次 |
| 最近记录: |