validate
depends
go
node
shape
node
shape
time
n1
s1
n11
s11
n1
s2
n11
s11
n2
s1
n11
s11
n2
s2
n11
s11
n3
s3
n4
s3
n5
s5
n7
s7
n6
s5
n7
s7
n9
s9
n8
s7
n9
s9
n3
s4
n10
s9
n11
s11
n12
s11
⛔ Simple Single
// Single Thread // // return function () { var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); // Simulate creating a validator with a schema. var validator = Validator.create(fixedMap); var start = Date.now(); var newResults = validator.validate(fixedMap, []); // Render newResults. newResults.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); // Create results structure and report. Util.createResults().merge(newResults).report(); return false; }
⛔ Promise Single
// Single Thread with promise // // return function () { var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); // Simulate creating a validator with a schema. var validator = Validator.create(fixedMap); var start = Date.now(); $("#go").prop( "disabled", true ); // never renders new Promise((accept, reject) => { accept(validator.validate(fixedMap, [])); }).then(newResults => { // Render newResults. newResults.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); // Create results structure and report. Util.createResults().merge(newResults).report(); $("#go").prop( "disabled", false ); }); return false; }
⛗ Progressive Single
// Single Thread // progressive rendering // stop button var abort = false, running = false; return function () { if (running) { // Emergency Stop button was pressed. abort = true; return false; } var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); for (var k in updateCells) updateCells[k].text("…").attr("class", "work"); // Simulate creating a validator with a schema. var validator = Validator.create(fixedMap); var currentEntry = 0; var results = Util.createResults(); running = true; $("#go").addClass("stoppable").text("stop"); var start = Date.now(); setTimeout(validateSingleEntry, 0); return false; function validateSingleEntry () { if (abort) { // Emergency Stop button was pressed. log(`aborted at entry ${currentEntry}`); abort = running = false; $("#go").removeClass("stoppable").text("go"); } else if (currentEntry === fixedMap.length) { // Done -- show results and restore interface. results.report(); running = false; $("#go").removeClass("stoppable").text("go"); } else { var queryMap = [fixedMap[currentEntry++]]; // ShapeMap with single entry. var newResults = validator.validate(queryMap, results.getShapeMap()); // Render newResults. newResults.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); // Merge into results. results.merge(newResults); // Skip entries that were already processed. while (currentEntry < fixedMap.length && results.has(fixedMap[currentEntry])) { console.log(currentEntry, fixedMap[currentEntry]); ++currentEntry; } // Call this function again after yielding. setTimeout(validateSingleEntry, 0); } } }
⛗ Progressive Promise
// Single Thread // progressive rendering // stop button var abort = false, running = false; return function () { if (running) { // Emergency Stop button was pressed. abort = true; return false; } var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); for (var k in updateCells) updateCells[k].text("…").attr("class", "work"); // Simulate creating a validator with a schema. var validator = Validator.create(fixedMap); var currentEntry = 0; var results = Util.createResults(); running = true; $("#go").addClass("stoppable").text("stop"); var start = Date.now(); setTimeout(validateSingleEntry, 0); return false; function validateSingleEntry () { if (abort) { // Emergency Stop button was pressed. log(`aborted at entry ${currentEntry}`); abort = running = false; $("#go").removeClass("stoppable").text("go"); } else if (currentEntry === fixedMap.length) { // Done -- show results and restore interface. results.report(); running = false; $("#go").removeClass("stoppable").text("go"); } else { var queryMap = [fixedMap[currentEntry++]]; // ShapeMap with single entry. new Promise((accept, reject) => { accept(validator.validate(queryMap, results.getShapeMap())); }).then(newResults => { // Render newResults. newResults.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); // Merge into results. results.merge(newResults); // Skip entries that were already processed. while (currentEntry < fixedMap.length && results.has(fixedMap[currentEntry])) ++currentEntry; // Call this function again after yielding. setTimeout(validateSingleEntry, 0); }); } } }
⛔ Simple Worker
// Simple WebWorker // // var ShExWorker = new Worker("apiDemoWorker.js"); return function () { var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); for (var k in updateCells) updateCells[k].text("…").attr("class", "work"); ShExWorker.onmessage = expectCreated; ShExWorker.postMessage({ request: "create", fixedMap: fixedMap}); $("#go").prop( "disabled", true ); var start = Date.now(); function expectCreated (msg) { if (msg.data.response !== "created") throw "expected created: " + JSON.stringify(msg.data); ShExWorker.onmessage = parseUpdatesAndResults; ShExWorker.postMessage({request: "validate", queryMap: fixedMap}); } function parseUpdatesAndResults (msg) { switch (msg.data.response) { case "done": console.dir(msg.data.results); msg.data.results.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); // Create results structure and report. Util.createResults().merge(msg.data.results).report(); $("#go").prop( "disabled", false ); break; default: log("<span class=\"error\">unknown response: " + JSON.stringify(msg.data) + "</span>"); } } return false; }
⛕ Killer Worker
// Killer WebWorker // // brutal stop button var abort = false, running = false; var ShExWorker = new Worker("apiDemoWorker.js"); return function () { if (running) { // Emergency Stop button was pressed. if (ShExWorker.onmessage !== null) { ShExWorker.terminate(); ShExWorker = new Worker("apiDemoWorker.js"); log("terminated web worker"); ShExWorker.onmessage = abort = running = false; $("#go").removeClass("stoppable").text("go"); } return false; } var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); for (var k in updateCells) updateCells[k].text("…").attr("class", "work"); ShExWorker.onmessage = expectCreated; ShExWorker.postMessage({ request: "create", fixedMap: fixedMap}); running = true; $("#go").addClass("stoppable").text("stop"); var start = Date.now(); function expectCreated (msg) { if (msg.data.response !== "created") throw "expected created: " + JSON.stringify(msg.data); ShExWorker.onmessage = parseUpdatesAndResults; ShExWorker.postMessage({request: "validate", queryMap: fixedMap}); } function parseUpdatesAndResults (msg) { switch (msg.data.response) { case "done": console.dir(msg.data.results); msg.data.results.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); // Create results structure and report. Util.createResults().merge(msg.data.results).report(); ShExWorker.onmessage = running = false; $("#go").removeClass("stoppable").text("go"); break; default: log("<span class=\"error\">unknown response: " + JSON.stringify(msg.data) + "</span>"); } } return false; }
⛕ Streaming Worker
// Streaming WebWorker // progressive rendering // brutal stop button const USE_INCREMENTAL_RESULTS = false; var abort = false, running = false; var ShExWorker = new Worker("apiDemoStreamingWorker.js"); return function () { if (running) { // Emergency Stop button was pressed. if (ShExWorker.onmessage !== null) { ShExWorker.terminate(); ShExWorker = new Worker("apiDemoStreamingWorker.js"); log("terminated web worker"); ShExWorker.onmessage = abort = running = false; $("#go").removeClass("stoppable").text("go"); } return false; } var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); for (var k in updateCells) updateCells[k].text("…").attr("class", "work"); ShExWorker.onmessage = expectCreated; ShExWorker.postMessage({ request: "create", fixedMap: fixedMap}); var results = USE_INCREMENTAL_RESULTS ? Util.createResults() : "not used"; running = true; $("#go").addClass("stoppable").text("stop"); var start = Date.now(); function expectCreated (msg) { if (msg.data.response !== "created") throw "expected created: " + JSON.stringify(msg.data); ShExWorker.onmessage = parseUpdatesAndResults; ShExWorker.postMessage({ request: "validate", queryMap: fixedMap, options: {includeDoneResults: !USE_INCREMENTAL_RESULTS} }); } function parseUpdatesAndResults (msg) { switch (msg.data.response) { case "update": msg.data.results.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); if (USE_INCREMENTAL_RESULTS) { // Merge into results. results.merge(msg.data.results); } break; case "done": console.dir(msg.data); if (USE_INCREMENTAL_RESULTS) { results.report(); } else { // Create results structure and report. Util.createResults().merge(msg.data.results).report(); } ShExWorker.onmessage = running = false; $("#go").removeClass("stoppable").text("go"); break; default: log("<span class=\"error\">unknown response: " + JSON.stringify(msg.data) + "</span>"); } } return false; }
⛗ Interactive Worker
// Interactive WebWorker // progressive rendering // stop button const USE_INCREMENTAL_RESULTS = false; var abort = false, running = false; var ShExWorker = new Worker("apiDemoInteractiveWorker.js"); return function () { if (running) { // Emergency Stop button was pressed. if (ShExWorker.onmessage !== null) { ShExWorker.onmessage = expectAborted; log("aborting web worker..."); function expectAborted (msg) { if (["update", "done"].indexOf(msg.data.response) !== -1) return; if (msg.data.response !== "aborted") throw "expected aborted: " + JSON.stringify(msg.data); log("aborted at entry " + msg.data.stoppedAt); ShExWorker.onmessage = abort = running = false; $("#go").removeClass("stoppable").text("go"); } } ShExWorker.postMessage({ request: "abort" }); abort = true; return false; } var fixedMap = Iface.parseShapeMap("tr"); var updateCells = Iface.indexResultCells("tr"); // Index the ShapeMap by node/shape pair. var index = Util.indexShapeMap(fixedMap); for (var k in updateCells) updateCells[k].text("…").attr("class", "work"); ShExWorker.onmessage = expectCreated; ShExWorker.postMessage({ request: "create", fixedMap: fixedMap}); var results = USE_INCREMENTAL_RESULTS ? Util.createResults() : "not used"; running = true; $("#go").addClass("stoppable").text("stop"); var start = Date.now(); function expectCreated (msg) { if (msg.data.response !== "created") throw "expected created: " + JSON.stringify(msg.data); ShExWorker.onmessage = parseUpdatesAndResults; ShExWorker.postMessage({ request: "validate", queryMap: fixedMap, options: {includeDoneResults: !USE_INCREMENTAL_RESULTS} }); } function parseUpdatesAndResults (msg) { switch (msg.data.response) { case "update": msg.data.results.forEach(newRes => { var key = Util.indexKey(newRes.node, newRes.shape); if (key in index) { markResult(updateCells[key], newRes.status, start); } else { extraResult(newRes); } }); if (USE_INCREMENTAL_RESULTS) { // Merge into results. results.merge(msg.data.results); } break; case "done": console.dir(msg.data); if (USE_INCREMENTAL_RESULTS) { results.report(); } else { // Create results structure and report. Util.createResults().merge(msg.data.results).report(); } ShExWorker.onmessage = running = false; $("#go").removeClass("stoppable").text("go"); break; default: log("<span class=\"error\">unknown response: " + JSON.stringify(msg.data) + "</span>"); } } return false; }