Create ChefWorker and move bake process into it
This commit is contained in:
parent
ff78c72d54
commit
760ab688b2
81
src/core/ChefWorker.js
Normal file
81
src/core/ChefWorker.js
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* Web Worker to handle communications between the front-end and the core.
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2017
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "babel-polyfill";
|
||||||
|
import Chef from "./Chef.js";
|
||||||
|
|
||||||
|
// Set up Chef instance
|
||||||
|
self.chef = new Chef();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Respond to message from parent thread.
|
||||||
|
*
|
||||||
|
* Messages should have the following format:
|
||||||
|
* {
|
||||||
|
* action: "bake" | "silentBake",
|
||||||
|
* data: {
|
||||||
|
* input: {string},
|
||||||
|
* recipeConfig: {[Object]},
|
||||||
|
* options: {Object},
|
||||||
|
* progress: {number},
|
||||||
|
* step: {boolean}
|
||||||
|
* } | undefined
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
self.addEventListener("message", function(e) {
|
||||||
|
// Handle message
|
||||||
|
switch (e.data.action) {
|
||||||
|
case "bake":
|
||||||
|
bake(e.data.data);
|
||||||
|
break;
|
||||||
|
case "silentBake":
|
||||||
|
silentBake(e.data.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Baking handler
|
||||||
|
*/
|
||||||
|
async function bake(data) {
|
||||||
|
try {
|
||||||
|
const response = await self.chef.bake(
|
||||||
|
data.input, // The user's input
|
||||||
|
data.recipeConfig, // The configuration of the recipe
|
||||||
|
data.options, // Options set by the user
|
||||||
|
data.progress, // The current position in the recipe
|
||||||
|
data.step // Whether or not to take one step or execute the whole recipe
|
||||||
|
);
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "bakeSuccess",
|
||||||
|
data: response
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
self.postMessage({
|
||||||
|
action: "bakeError",
|
||||||
|
data: err
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Silent baking handler
|
||||||
|
*/
|
||||||
|
function silentBake(data) {
|
||||||
|
const duration = self.chef.silentBake(data.recipeConfig);
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "silentBakeComplete",
|
||||||
|
data: duration
|
||||||
|
});
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import Utils from "../core/Utils.js";
|
import Utils from "../core/Utils.js";
|
||||||
import Chef from "../core/Chef.js";
|
import ChefWorker from "worker-loader!../core/ChefWorker.js";
|
||||||
import Manager from "./Manager.js";
|
import Manager from "./Manager.js";
|
||||||
import HTMLCategory from "./HTMLCategory.js";
|
import HTMLCategory from "./HTMLCategory.js";
|
||||||
import HTMLOperation from "./HTMLOperation.js";
|
import HTMLOperation from "./HTMLOperation.js";
|
||||||
@ -27,7 +27,7 @@ const App = function(categories, operations, defaultFavourites, defaultOptions)
|
|||||||
this.doptions = defaultOptions;
|
this.doptions = defaultOptions;
|
||||||
this.options = Utils.extend({}, defaultOptions);
|
this.options = Utils.extend({}, defaultOptions);
|
||||||
|
|
||||||
this.chef = new Chef();
|
this.chefWorker = new ChefWorker();
|
||||||
this.manager = new Manager(this);
|
this.manager = new Manager(this);
|
||||||
|
|
||||||
this.baking = false;
|
this.baking = false;
|
||||||
@ -36,7 +36,7 @@ const App = function(categories, operations, defaultFavourites, defaultOptions)
|
|||||||
this.progress = 0;
|
this.progress = 0;
|
||||||
this.ingId = 0;
|
this.ingId = 0;
|
||||||
|
|
||||||
window.chef = this.chef;
|
this.chefWorker.addEventListener("message", this.handleChefMessage.bind(this));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -99,16 +99,21 @@ App.prototype.setBakingStatus = function(bakingStatus) {
|
|||||||
|
|
||||||
let inputLoadingIcon = document.querySelector("#input .title .loading-icon"),
|
let inputLoadingIcon = document.querySelector("#input .title .loading-icon"),
|
||||||
outputLoadingIcon = document.querySelector("#output .title .loading-icon"),
|
outputLoadingIcon = document.querySelector("#output .title .loading-icon"),
|
||||||
|
inputElement = document.querySelector("#input-text"),
|
||||||
outputElement = document.querySelector("#output-text");
|
outputElement = document.querySelector("#output-text");
|
||||||
|
|
||||||
if (bakingStatus) {
|
if (bakingStatus) {
|
||||||
inputLoadingIcon.style.display = "inline-block";
|
inputLoadingIcon.style.display = "inline-block";
|
||||||
outputLoadingIcon.style.display = "inline-block";
|
outputLoadingIcon.style.display = "inline-block";
|
||||||
|
inputElement.classList.add("disabled");
|
||||||
|
inputElement.disabled = true;
|
||||||
outputElement.classList.add("disabled");
|
outputElement.classList.add("disabled");
|
||||||
outputElement.disabled = true;
|
outputElement.disabled = true;
|
||||||
} else {
|
} else {
|
||||||
inputLoadingIcon.style.display = "none";
|
inputLoadingIcon.style.display = "none";
|
||||||
outputLoadingIcon.style.display = "none";
|
outputLoadingIcon.style.display = "none";
|
||||||
|
inputElement.classList.remove("disabled");
|
||||||
|
inputElement.disabled = false;
|
||||||
outputElement.classList.remove("disabled");
|
outputElement.classList.remove("disabled");
|
||||||
outputElement.disabled = false;
|
outputElement.disabled = false;
|
||||||
}
|
}
|
||||||
@ -116,30 +121,58 @@ App.prototype.setBakingStatus = function(bakingStatus) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the Chef to bake the current input using the current recipe.
|
* Asks the ChefWorker to bake the current input using the current recipe.
|
||||||
*
|
*
|
||||||
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
|
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
|
||||||
* whole recipe.
|
* whole recipe.
|
||||||
*/
|
*/
|
||||||
App.prototype.bake = async function(step) {
|
App.prototype.bake = function(step) {
|
||||||
let response;
|
|
||||||
|
|
||||||
if (this.baking) return;
|
if (this.baking) return;
|
||||||
|
|
||||||
this.setBakingStatus(true);
|
this.setBakingStatus(true);
|
||||||
|
|
||||||
try {
|
this.chefWorker.postMessage({
|
||||||
response = await this.chef.bake(
|
action: "bake",
|
||||||
this.getInput(), // The user's input
|
data: {
|
||||||
this.getRecipeConfig(), // The configuration of the recipe
|
input: this.getInput(), // The user's input
|
||||||
this.options, // Options set by the user
|
recipeConfig: this.getRecipeConfig(), // The configuration of the recipe
|
||||||
this.progress, // The current position in the recipe
|
options: this.options, // Options set by the user
|
||||||
step // Whether or not to take one step or execute the whole recipe
|
progress: this.progress, // The current position in the recipe
|
||||||
);
|
step: step // Whether or not to take one step or execute the whole recipe
|
||||||
} catch (err) {
|
}
|
||||||
this.handleError(err);
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for messages sent back by the ChefWorker.
|
||||||
|
*
|
||||||
|
* @param {MessageEvent} e
|
||||||
|
*/
|
||||||
|
App.prototype.handleChefMessage = function(e) {
|
||||||
|
switch (e.data.action) {
|
||||||
|
case "bakeSuccess":
|
||||||
|
this.bakingComplete(e.data.data);
|
||||||
|
break;
|
||||||
|
case "bakeError":
|
||||||
|
this.handleError(e.data.data);
|
||||||
|
this.setBakingStatus(false);
|
||||||
|
break;
|
||||||
|
case "silentBakeComplete":
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error("Unrecognised message from ChefWorker", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for completed bakes.
|
||||||
|
*
|
||||||
|
* @param {Object} response
|
||||||
|
*/
|
||||||
|
App.prototype.bakingComplete = function(response) {
|
||||||
this.setBakingStatus(false);
|
this.setBakingStatus(false);
|
||||||
|
|
||||||
if (!response) return;
|
if (!response) return;
|
||||||
@ -174,23 +207,27 @@ App.prototype.autoBake = function() {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a silent bake forcing the browser to load and cache all the relevant JavaScript code needed
|
* Asks the ChefWorker to run a silent bake, forcing the browser to load and cache all the relevant
|
||||||
* to do a real bake.
|
* JavaScript code needed to do a real bake.
|
||||||
*
|
*
|
||||||
* The output will not be modified (hence "silent" bake). This will only actually execute the
|
* The output will not be modified (hence "silent" bake). This will only actually execute the recipe
|
||||||
* recipe if auto-bake is enabled, otherwise it will just load the recipe, ingredients and dish.
|
* if auto-bake is enabled, otherwise it will just wake up the ChefWorker with an empty recipe.
|
||||||
*
|
|
||||||
* @returns {number} - The number of miliseconds it took to run the silent bake.
|
|
||||||
*/
|
*/
|
||||||
App.prototype.silentBake = function() {
|
App.prototype.silentBake = function() {
|
||||||
let startTime = new Date().getTime(),
|
let recipeConfig = [];
|
||||||
recipeConfig = this.getRecipeConfig();
|
|
||||||
|
|
||||||
if (this.autoBake_) {
|
if (this.autoBake_) {
|
||||||
this.chef.silentBake(recipeConfig);
|
// If auto-bake is not enabled we don't want to actually run the recipe as it may be disabled
|
||||||
|
// for a good reason.
|
||||||
|
recipeConfig = this.getRecipeConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Date().getTime() - startTime;
|
this.chefWorker.postMessage({
|
||||||
|
action: "silentBake",
|
||||||
|
data: {
|
||||||
|
recipeConfig: recipeConfig
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
|
||||||
|
transition: all 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#output-html {
|
#output-html {
|
||||||
@ -90,10 +92,10 @@
|
|||||||
|
|
||||||
@keyframes spinner {
|
@keyframes spinner {
|
||||||
from {
|
from {
|
||||||
transform:rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform:rotate(359deg);
|
transform: rotate(359deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user