Refactor WebWorker interfacing code into own class

This commit is contained in:
Starbeamrainbowlabs 2019-07-26 12:33:47 +01:00
parent 52d4f4fb38
commit 673a8e3441
2 changed files with 80 additions and 58 deletions

View file

@ -3,6 +3,7 @@
import L from 'leaflet'; import L from 'leaflet';
import chroma from 'chroma-js'; import chroma from 'chroma-js';
import WorkerWrapper from './WorkerWrapper.mjs';
import GetFromUrl from './Helpers/GetFromUrl.mjs'; import GetFromUrl from './Helpers/GetFromUrl.mjs';
import Config from './ClientConfig.mjs'; import Config from './ClientConfig.mjs';
@ -37,67 +38,12 @@ class LayerAI {
*/ */
constructor(map) { constructor(map) {
this.map = map; this.map = map;
this.worker = new Worker("worker.js"); // We could pass { type: "module" } as the 2nd argument here to allow Rollup code splitting to function as normal, but it's not supported by browsers yet this.worker = new WorkerWrapper();
this.map_bounds = null; this.map_bounds = null;
} }
/**
* Sets up the Web Worker that does the TensorFlow prediction.
* Using a web worker avoids hanging the main thread.
* @return {Promise} A Promise that resolves when setup is complete.
*/
worker_setup() {
// Arrow functions inherit the parent scope, including the "this"
// special variable.
return new Promise((resolve, reject) => {
// Attach the listener first
this.worker.addEventListener("message", (event) => {
if(event.data.event !== "setup-complete") {
reject(`Error: AIWorker responded with event ${event.data.event}, but 'setup-complete' was expected.`, event.data);
return;
}
resolve();
}, { once: true });
// Ask the web worker to set itself up
this.worker.postMessage({
event: "setup",
setup_info: {
bounds: this.map_bounds,
index: this.index,
Config
}
});
})
}
/**
* Uses the Web Worker to predict a row of signal strength values.
* @param {number} latitude The latitude for which predictions should be made.
* @return {Promise<number[]>} A Promise returning the array of predictions calculated by the web worker.
*/
worker_predict_row(latitude) {
return new Promise((resolve, reject) => {
// Attach the event listener....
this.worker.addEventListener("message", (event) => {
if(event.data.event !== "result") {
reject(`Error: AIWorker responded with event ${event.data.event}, but 'result' was expected.`, event.data);
return;
}
resolve(event.data);
}, { once: true });
// ....and send the request
this.worker.postMessage({
event: "predict-row",
latitude
});
});
}
/** /**
* Sets up the Leaflet AI visualisation layer. * Sets up the Leaflet AI visualisation layer.
@ -120,7 +66,7 @@ class LayerAI {
this.map_bounds.west -= Config.border.lng; this.map_bounds.west -= Config.border.lng;
// Setup the web worker // Setup the web worker
await this.worker_setup(); await this.worker.setup(this.map_bounds, this.index);
// Generate the Leaflet layer // Generate the Leaflet layer
this.layer = await this.generate_layer(); this.layer = await this.generate_layer();
@ -170,7 +116,7 @@ class LayerAI {
}; };
for(let lat = this.map_bounds.south; lat < this.map_bounds.north; lat += Config.step.lat) { for(let lat = this.map_bounds.south; lat < this.map_bounds.north; lat += Config.step.lat) {
let next_result = await this.worker_predict_row(lat); let next_result = await this.worker.predict_row(lat);
let lng = this.map_bounds.west; let lng = this.map_bounds.west;
// Keep up with the statistics // Keep up with the statistics
@ -205,6 +151,8 @@ class LayerAI {
} }
} }
this.worker.end(this.worker);
console.log("Stats:", stats); console.log("Stats:", stats);
return coverage; return coverage;

View file

@ -0,0 +1,74 @@
"use strict";
import Config from './ClientConfig.mjs';
class WorkerWrapper {
constructor() {
this.worker = new Worker("worker.js"); // We could pass { type: "module" } as the 2nd argument here to allow Rollup code splitting to function as normal, but it's not supported by browsers yet
}
/**
* Sets up the Web Worker that does the TensorFlow prediction.
* Using a web worker avoids hanging the main thread.
* @return {Promise} A Promise that resolves when setup is complete.
*/
setup(map_bounds, index) {
// Arrow functions inherit the parent scope, including the "this"
// special variable.
return new Promise((resolve, reject) => {
// Attach the listener first
this.worker.addEventListener("message", (event) => {
if(event.data.event !== "setup-complete") {
reject(`Error: AIWorker responded with event ${event.data.event}, but 'setup-complete' was expected.`, event.data);
return;
}
resolve();
}, { once: true });
// Ask the web worker to set itself up
this.worker.postMessage({
event: "setup",
setup_info: {
bounds: map_bounds,
index,
Config
}
});
})
}
/**
* Uses the Web Worker to predict a row of signal strength values.
* @param {number} latitude The latitude for which predictions should be made.
* @return {Promise<number[]>} A Promise returning the array of predictions calculated by the web worker.
*/
predict_row(latitude) {
return new Promise((resolve, reject) => {
// Attach the event listener....
this.worker.addEventListener("message", (event) => {
if(event.data.event !== "result") {
reject(`Error: AIWorker responded with event ${event.data.event}, but 'result' was expected.`, event.data);
return;
}
resolve(event.data);
}, { once: true });
// ....and send the request
this.worker.postMessage({
event: "predict-row",
latitude
});
});
}
end() {
this.worker.postMessage({
event: "end"
})
}
}
export default WorkerWrapper;