Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

implement a new web worker demo

  • Loading branch information...
commit b74ad4d9938dfda00a3691f539aa46da33a66025 1 parent cc93513
@joelrbrandt joelrbrandt authored
View
120 demos/worker.html
@@ -1,82 +1,38 @@
-<title>Worker</title>
- <article>
- <p>Canvas is running whilst an prime number finder runs in a worker</p>
- <p>Prime found: <span id="status">0</span></p>
- <div><input type="button" value="start worker" id="toggleWorker" /></div>
- </article>
-<script>
-
-buildSpinner({ x : 50, y : 50, size : 20, degrees : 30 });
-
-var w = new Worker('/js/cruncher.js');
-
-addEvent(document.getElementById('toggleWorker'), 'click', function () {
- w.postMessage('');
-});
-
-w.onmessage = function (event) {
- if (event.data && (event.data+"").match(/^log:/i)) {
- console.log(event.data.match(/^log:\s*(.*)/)[1]);
- } else {
- document.querySelector('#status').innerHTML = event.data;
- }
-}
-
-function buildSpinner(data) {
-
- var canvas = document.createElement('canvas');
- canvas.height = 100;
- canvas.width = 300;
- document.querySelector('article').appendChild(canvas);
- var ctx = canvas.getContext("2d"),
- i = 0, degrees = data.degrees, loops = 0, degreesList = [];
-
- for (i = 0; i < degrees; i++) {
- degreesList.push(i);
- }
-
- // reset
- i = 0;
-
- // so I can kill it later
- window.canvasTimer = setInterval(draw, 1000/degrees);
-
- function reset() {
- ctx.clearRect(0,0,100,100); // clear canvas
-
- var left = degreesList.slice(0, 1);
- var right = degreesList.slice(1, degreesList.length);
- degreesList = right.concat(left);
- }
-
- function draw() {
- var c, s, e;
-
- var d = 0;
-
- if (i == 0) {
- reset();
- }
-
- ctx.save();
-
- d = degreesList[i];
- c = Math.floor(255/degrees*i);
- ctx.strokeStyle = 'rgb(' + c + ', ' + c + ', ' + c + ')';
- ctx.lineWidth = data.size;
- ctx.beginPath();
- s = Math.floor(360/degrees*(d));
- e = Math.floor(360/degrees*(d+1)) - 1;
-
- ctx.arc(data.x, data.y, data.size, (Math.PI/180)*s, (Math.PI/180)*e, false);
- ctx.stroke();
-
- ctx.restore();
-
- i++;
- if (i >= degrees) {
- i = 0;
- }
- }
-}
-</script>
+<html>
+<head>
+ <title>Worker</title>
+ <style>
+ body {
+ font-family: sans-serif;
+ }
+
+ #status {
+ height: 200px;
+ max-height: 200px;
+ border: thin solid black;
+ overflow-y: scroll;
+ }
+
+ #square {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 75px;
+ height: 75px;
+ background-color: rgba(0, 0, 220, 0.3);
+ z-index: -1;
+ }
+ </style>
+</head>
+<body>
+ <h1>Web Worker Demo</h1>
+ <p>Works in Chrome, Safari, and Firefox. Web worker portion works in Opera.</p>
+ <p>Use arrow keys to change the direction of the animated square. The square is animated with <em>requestAnimationFrame</em>.</p>
+ <p>Click the button below to start or stop the worker.</p>
+ <div><input type="button" value="start worker" id="toggleWorker" /></div>
+ <h2>Messages from Worker:</h2>
+ <div id="status"></div>
+ <div id="square"></div>
+<script src="../js/worker-main.js"></script>
+</body>
+</html>
View
24 js/cruncher.js
@@ -1,24 +0,0 @@
-var running = false;
-
-onmessage = function (event) {
- // doesn't matter what the message is, just toggle the worker
- if (running == false) {
- running = true;
- run();
- } else {
- running = false;
- }
-};
-
-function run() {
- var n = 1;
- search: while (running) {
- n += 1;
- for (var i = 2; i <= Math.sqrt(n); i += 1)
- if (n % i == 0)
- continue search;
- // found a prime!
- postMessage(n);
- }
-}
-
View
68 js/worker-cruncher.js
@@ -0,0 +1,68 @@
+/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */
+/*global postMessage, addEventListener */
+
+(function () {
+ "use strict";
+
+ var WHEN_TO_STOP = 10000000;
+ var COMPUTE_BLOCK_SIZE = 1000000;
+
+ var running = false;
+ var count = 0;
+
+ // We have to compute in blocks of ~1 second of computation in order to make sure
+ // that we read our message queue occasionally. Worker threads are not preemptive
+ // (like all JS), so if we don't pause computation to read the message queue, we'll
+ // be unresponsive to user requests.
+ function compute(start) {
+ var n = start;
+ var i, hasDivisor;
+
+ if (!running) { // got a message to stop before this call to compute
+ postMessage("Stopped!");
+ } else {
+ while (n < start + COMPUTE_BLOCK_SIZE) {
+ hasDivisor = false;
+ for (i = 2; i <= Math.sqrt(n); i += 1) {
+ if (n % i === 0) {
+ hasDivisor = true;
+ break;
+ }
+ }
+ if (!hasDivisor) {
+ // found a prime!
+ count++;
+ }
+ n += 1;
+ }
+
+ if (n < WHEN_TO_STOP) {
+ // allow for event loop to actually forward messages to the worker
+ setTimeout(function () { compute(n); }, 1);
+ } else {
+ // we reached the end
+ running = false;
+ postMessage("Done!");
+ }
+ }
+
+ // Finally, always report how many primes we've found so far
+ postMessage("Found " + count + " primes between 2 and " + (n - 1));
+
+ }
+
+ addEventListener('message', function (event) {
+ // doesn't matter what the message is, just toggle the worker
+ if (running === false) {
+ postMessage("Starting...");
+ count = 0;
+ running = true;
+ compute(1);
+ } else {
+ postMessage("Stopping...");
+ running = false;
+ }
+ });
+
+
+}());
View
92 js/worker-main.js
@@ -0,0 +1,92 @@
+/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, browser: true */
+/*global Worker */
+
+(function () {
+ "use strict";
+
+ var SQUARE_SIZE = 75;
+ var MOVEMENT_STEP = 3;
+
+ var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
+ window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
+
+
+ // Set up the worker
+ var running = false;
+ var statusDiv = document.getElementById('status');
+ var button = document.getElementById('toggleWorker');
+ var worker = new Worker('../js/worker-cruncher.js');
+ worker.addEventListener('message', function (event) {
+ var currentStatus = statusDiv.innerHTML;
+ statusDiv.innerHTML = "<p>" + event.data + "</p>" + currentStatus;
+ if (event.data === "Done!") {
+ running = false;
+ button.value = "start worker";
+ }
+ });
+
+ button.onclick = function () {
+ running = !running;
+ if (running) {
+ statusDiv.innerHTML = "";
+ button.value = "stop worker";
+ } else {
+ button.value = "start worker";
+ }
+ worker.postMessage('');
+
+ };
+
+
+ // Set up the animated square
+ var square = document.getElementById('square');
+ var direction = 39; // right
+
+ square.style.top = 0;
+ square.style.left = 20;
+ square.style.height = SQUARE_SIZE;
+ square.style.width = SQUARE_SIZE;
+
+ function moveSquare() {
+ var left = parseInt(square.style.left, 10);
+ var top = parseInt(square.style.top, 10);
+ var right = left + SQUARE_SIZE;
+ var bottom = top + SQUARE_SIZE;
+
+ switch (direction) {
+ case 37: // left
+ if (left > 0) {
+ square.style.left = left - MOVEMENT_STEP;
+ }
+ break;
+ case 38: // up
+ if (top > 0) {
+ square.style.top = top - MOVEMENT_STEP;
+ }
+ break;
+ case 39: //right
+ if (right < document.documentElement.clientWidth) {
+ square.style.left = left + MOVEMENT_STEP;
+ }
+ break;
+ case 40: // down
+ if (bottom < document.documentElement.clientHeight) {
+ square.style.top = top + MOVEMENT_STEP;
+ }
+ break;
+ default:
+ break;
+ }
+ requestAnimationFrame(moveSquare);
+ }
+
+ window.onkeydown = function (event) {
+ if (event.keyCode >= 37 && event.keyCode <= 40) { // is an arrow key
+ direction = event.keyCode;
+ }
+ };
+
+ // start the square animating
+ requestAnimationFrame(moveSquare);
+
+}());
View
23 js/worker.js
@@ -1,23 +0,0 @@
-var running = false;
-var ctr = 0;
-
-function log(s) {
- postMessage('log:' + s);
-}
-
-onmessage = function (event) {
- // doesn't matter what the message is, just toggle the worker
- if (running == false) {
- running = true;
- run();
- } else {
- running = false;
- }
-};
-
-function run() {
- while (running) {
- postMessage(ctr);
- ctr++;
- }
-}
Please sign in to comment.
Something went wrong with that request. Please try again.