I want to use web worker in my code, and to avoid subtle problems, I read this section of MDN. MDN states the code below is "of a catastrophy", so I guess the codes will cause some strange behaviors impalpablely.
The codes intends to create a canvas, whose content comes from a web worker. The web worker generates the image data in 60FPS and post a message contains the image data to main.js. But MDN doesn't explain what exactly problem will occur, so I have to guess.
- The screen can't be refreshed in 60FPS, say if 50FPS, because of the
context.putImageData(imageData);takes a little longer time if drawing a retina screen, the posted message from web worker cannot get a in time response, so the posted message will be accumulated to cause the main screen locking or no response? - If the "Data passed between the main page and workers is copied, not shared.", would the situation in 1 means serious memory leak?
- ... Needs your help to point problems.
Vise versa, if the code is written as main.js calls the data from web worker, for example postMessage to web worker to query, but in very high frequency, and the algorithm in web worker would take relatively long time, cannot response in time to main.js, what would happen?
Or my understanding is wrong, the problems the codes want to demonstrate are totally different.
Needs your help. Thanks in advance.
HTML Content
<html>
<head>
<title>Multithreading Catastrophy</title>
<style>
body { margin: 0px; }
canvas { position: absolute; top: 0; bottom: 0; left: 0; right:0; width: 100%; height: 100%; }
</style>
<script src="main.js" async></script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
main.js Content
// main.js
var myworker = new Worker("worker.js"), width=window.innerWidth, height=window.innerHeight, context=document.getElementById('canvas').getContext('2d');
var imagedatatmp=context.createImageData(width,height);
myworker.onmessage = function(data){
imageData = imagedatatmp.from(data);
};
setTimeout(function draw_canvas() {
context.putImageData(imageData);
setTimeout(draw_canvas, 1000/60);
},10);
window.onresize = window.reload; // Quick (to type) n' dirty way to resize;
worker.js Content
// worker.js
window.onmessage = function(width, height){
var noise = function(x, y, z) {
var p = new Array(512), permutation = [151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180];
for (var i = 0;i < 256;i++) p[256 + i] = p[i] = permutation[i];
var X = Math.floor(x) & 255, Y = Math.floor(y) & 255, Z = Math.floor(z) & 255; x -= Math.floor(x), y -= Math.floor(y), z -= Math.floor(z);
var u = fade(x), v = fade(y), w = fade(z);
var A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
return scale(lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z), grad(p[BA], x - 1, y, z)), lerp(u, grad(p[AB], x, y - 1, z), grad(p[BB], x - 1, y - 1, z))), lerp(v, lerp(u, grad(p[AA + 1], x, y, z - 1), grad(p[BA + 1], x - 1, y, z - 1)), lerp(u, grad(p[AB + 1], x, y - 1, z - 1), grad(p[BB + 1], x - 1, y - 1, z - 1)))));
};
function fade(t) { return t * t * t * (t * (t * 6 - 15) + 10); }
function lerp(t, a, b) { return a + t * (b - a); }
function grad(hash, x, y, z) {
var h = hash & 15; var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
function scale(n) { return (1 + n) / 2; }
var length = width*height; var canvasnoisedata=new UInt32Array(length);
setTimeout(function make_noise() {
var i=length, z=Math.random()*1024;
while ( i-- ) {
canvasnoisedata[i] = noise(i%width+z,i/width+z,z);
}
setTimeout(make_noise, 1000/60);
},1000/60);
setTimeout(function post_noise() {
postMessage( canvasnoisedata );
setTimeout(post_noise, 1000/60);
},1000/60);
};