(function (d, w, undefined) { const ww = new Worker(getInlineJS()); const tresholdselector = d.querySelector('#treshold'); const print = Helpers.log2Screen; tresholdselector.addEventListener('change', start); start(); ww.onmessage = e => { // status message during calculation if (e.data.status) { return print( 'Found <code>' + e.data.found + '</code> prime numbers', {clear: true, direct: true} ); } d.querySelector('#waiting').classList.add("hidden"); $('#warning').addClass('hidden'); // print result print( e.data.msg, ', calculation took ', e.data.duration, ' millisecond', e.data.duration != 1 ? 's': '', e.data.primes && e.data.primes.length > 10000 ? '<br><b class="warn">Busy</b> ' + '(reflow/repaint takes time and unfortunaly that\'s blocking)' : '', '<h3>Prime numbers listing</h3>', {clear: true, direct: true} ); warnWait(); setTimeout(() => { let xresult = d.createElement('div'); xresult.id = "PRIMES"; xresult.style.display = "none"; xresult.innerHTML = e.data.primes.join(' '); d.body.appendChild(xresult); xresult.style.display = ""; warnWait(true, "Done"); }, 10); }; function warnWait(end, replaceText) { const warner = d.querySelector('b.warn'); if (!warner) {return true;} var action = end ? "remove" : "add"; warner.classList[action]("spin"); warner.textContent = replaceText || warner.textContent; } function start() { const previous = d.querySelector("#PRIMES"); if (previous) {d.body.removeChild(previous);} print('start working...', {clear:true, direct: true}); $('#warning')[+tresholdselector.value > 100000 ? 'removeClass' : 'addClass']('hidden'); d.querySelector('#waiting').classList.remove("hidden"); ww.postMessage({value: tresholdselector.value}); } function getInlineJS() { const ecmaCode = d.querySelector('[data-isworker]').textContent; const ecmaBlob = new Blob([ecmaCode], {"type": "application\/javascript"}); return URL.createObjectURL(ecmaBlob); } }(document, window))
<div class="solink" data-linkid="26312971"></div> <h3>Using a web worker to calculate prime numbers from 0 to [Threshold]</h3> <p id="chunking"></p> <div id="waiting" class="hidden"><b class="working spin">Working</b> (Browser is <i>not</i> blocked)</div> Threshold: <select id="treshold"> <option value="10">10</option> <option value="100" selected="selected">100</option> <option value="1000">1000</option> <option value="10000">10,000</option> <option value="100000">100,000</option> <option value="1000000">1,000,000</option> <option value="10000000">10,000,000</option> <option value="100000000">100,000,000</option> </select> <script type="text/ecmaworker" data-isworker="true"> String.prototype.padLeft = String.prototype.padLeft || function padLeft(base, chr) { var len = (String(base || 10).length - String(this).length) + 1; return len > 0 ? new Array(len).join(chr || '0') + this : this; }; Number.prototype.pretty = function (usa, noprecision){ const somenum = this; const dec = (''+somenum).split(/[.,]/); const lendec = dec[1] ? dec[1].length : 0 const precision = lendec && !noprecision ? decPrecise(somenum,lendec) : dec[1] const sep = usa ? ',' : '.'; const decsep = usa ? '.' : ','; // from http://stackoverflow.com/questions/10473994/javascript-adding-decimal-numbers-issue/10474209 function decPrecise(d,l){ return String(d.toFixed(12)).split(/[.,]/)[1].substr(0,l); } function xsep(num,sep) { let n = String(num).split(''); let i = -3; while (n.length + i > 0) { n.splice(i, 0, sep); i -= 4; } return n.join(''); } return xsep(dec[0],sep) + (dec[1] ? decsep+precision :''); } onmessage = function (e) { let n = 0; let total = 0; const THRESHOLD = +e.data.value; const startTime = new Date; const padFactor = Math.floor(THRESHOLD/10); let primes = []; while (++n < THRESHOLD) { let isprime = isPrime(n); total += isprime ? 1 : 0; void( isprime && (primes.push(String(n).padLeft(padFactor, ' ')), primes.length % 100 < 1 && postMessage({status: true, found: primes.length})) ); } postMessage({ msg: 'Found <code>' + total.pretty(1) + '</code> prime numbers using threshold <code>' + THRESHOLD.pretty(1) + '</code>', primes: primes, duration: (new Date - startTime).pretty(1)}); function isPrime(number) { if (number % 2 === 0 && number > 2) { return false; } let start = 2; const limit = Math.sqrt(number); while (start <= limit) { if (number % start++ < 1) return false; } return number > 1; } } </script>
#theChunks { margin-top: 1.5em; } #warning { color: red; font-weight: bold; } .hidden { display: none; } .numbers { font-family: courier new; } #PRIMES { font-family: courier new; white-space: pre-line; } #waiting { width: 300px; height: 1.2em; position: relative; margin-bottom: 1em; } .wait { width: 20px; position: absolute; top: 0; bottom: 0; background-color: red; transition: all ease-in-out 0.1s 0s; } @keyframes spinner { from { -moz-transform: rotateY(0deg); -ms-transform: rotateY(0deg); transform: rotateY(0deg); } to { -moz-transform: rotateY(-360deg); -ms-transform: rotateY(-360deg); transform: rotateY(-360deg); } } .warn, .working { color: red; } .spin { display: inline-block; animation: spinner 1s linear infinite; }