Chucked Web Worker

Warning: Your browser doesn't support Web Workers.
One of the drawbacks of the simple web worker approach is that the worker is unable to respond to messages posted while still busy. Using a chunking approach means we split the work up into "chunks" allowing the web worker to process other incoming messages between the different chunks.

Demo

The in page JavaScript

var worker = null;
$('#btnStart').click(function () {
    if (!worker) {
        $('#primes').empty();
        if (!!window.Worker) {
            worker = new Worker('/Scripts/ChunkedPrimes.js');
            worker.onmessage = function (e) {
                $('<li>').text(e.data).prependTo('#primes');
            };
        } else {
            $('<li>').text('Web Worker is not supported :-(').prependTo('#primes');
        }
    }
});

$('#btnStop').click(function () {
    if (worker) {
        worker.terminate();
        worker = null;
        $('<li>').text('Terminated').prependTo('#primes');
    }
});

$('#btnPause').click(function () {
    if (worker) {
        $('<li>').text('Pause').prependTo('#primes');
        worker.postMessage('pause');
    }
});

$('#btnResume').click(function () {
    if (worker) {
        $('<li>').text('Resume').prependTo('#primes');
        worker.postMessage('resume');
    }
});

The ChunkedPrimes.js loaded bij the Worker object

var isPaused = false;

onmessage = function (e) {
    if (e.data == 'pause') {
        isPaused = true;
    } else if (e.data == 'resume') {
        isPaused = false;
        testPrime();
    }
};

var i = 2;
testPrime();

function testPrime() {
    var isPrime = true;
    for (var d = 2; d < i; d++) {
        if (i % d === 0) {
            isPrime = false;
            break;
        }
    }

    if (isPrime) {
        postMessage(i);
    }

    if (!isPaused) {
        if (i < 1000000) {
            i++;
            if (i % 1 == 100) {
                setTimeout(testPrime, 0);
            } else {
                testPrime();
            }
        }
    }
}