Master de II. ULL. 1er cuatrimestre. 2020/2021
See https://javascript.info/event-loop#use-case-1-splitting-cpu-hungry-tasks
To demonstrate the approach, for the sake of simplicity, let’s take a function that counts from 1 to a big number.
If you run the code below with a very large number, the engine will hang for some time.
When running it in-browser, try to click other buttons on the page – you’ll see that no other events get handled until the counting finishes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let i = 0;
let start = Date.now();
function count() {
// do a heavy job
for (let j = 0; j < 1e9; j++) {
i++;
}
alert("Done in " + (Date.now() - start) + 'ms');
}
count();
We can evade problems by splitting the big task into pieces. Do the first piece, then schedule setTimeout (with zero-delay) to do the next piece, and so on.
1
2
3
[~/.../tema2-async/event-loop(master)]$ pwd -P
/Users/casiano/campus-virtual/1920/dsi1920/ull-esit-dsi-1920.github.io/tema2-async/event-loop
[~/.../tema2-async/event-loop(master)]$ cat splitting-cpu-hungry-task.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE html>
<style>
#progress {color:green;}
</style>
<h1>Splitting CPU Hungry Tasks:When you check the checkbox, the text will change color</h1>
<input type="checkbox" id="checkResponsive">
<button disabled="disabled" id="progress">Click me!</button>
<script>
'use strict';
const checkResponsive = document.getElementById("checkResponsive");
const progress = document.getElementById("progress");
checkResponsive.addEventListener("change", (checkbox) => {
if (checkResponsive.checked) {
progress.style.color = "red";
} else{
progress.style.color = "green";
}
}
);
let start = Date.now();
const Big = 1e9;
const Small = 1e5;
let counter = 0;
let processChunk = (chunk) => {
let i = chunk;
do { // do a piece of the heavy job (*)
i++;
} while (i % Small != 0);
progress.innerHTML = i;
return i;
};
let stop = () => (counter == Big);
function count() {
if (stop()) {
progress.innerHTML = "Done in " + (Date.now() - start) + 'ms';
} else {
setTimeout(count); // schedule the new call (**)
};
counter = processChunk(counter);
}
count();
</script>