You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 2-ui/99-ui-misc/03-event-loop/article.md
+71-71Lines changed: 71 additions & 71 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,64 +1,64 @@
1
1
2
-
# Event loop: microtasks and macrotasks
2
+
# Event loop: microtasks și macrotasks
3
3
4
-
Browser JavaScript execution flow, as well as in Node.js, is based on an*event loop*.
4
+
Fluxul de execuție JavaScript din browser, ca și în Node.js, se bazează pe un*event loop*.
5
5
6
-
Understanding how event loop works is important for optimizations, and sometimes for the right architecture.
6
+
Înțelegerea modului în care funcționează event loop este importantă pentru optimizări, și uneori pentru arhitectura potrivită.
7
7
8
-
In this chapter we first cover theoretical details about how things work, and then see practical applications of that knowledge.
8
+
În acest capitol vom acoperi mai întâi detaliile teoretice despre cum funcționează lucrurile, iar apoi vom vedea aplicațiile practice ale acestor cunoștințe.
9
9
10
10
## Event Loop
11
11
12
-
The*event loop*concept is very simple. There's an endless loop, where the JavaScript engine waits for tasks, executes them and then sleeps, waiting for more tasks.
12
+
Conceptul*event loop*este foarte simplu. Există o buclă fără sfârșit, în care motorul JavaScript așteaptă sarcini, le execută și apoi adoarme, așteptând alte sarcini.
13
13
14
-
The general algorithm of the engine:
14
+
Algoritmul general al motorului:
15
15
16
-
1.While there are tasks:
17
-
-execute them, starting with the oldest task.
18
-
2.Sleep until a task appears, then go to 1.
16
+
1.În timp ce există sarcini:
17
+
-le execută, începând cu cea mai veche sarcină.
18
+
2.Doarme până când apare o sarcină, apoi treceți la 1.
19
19
20
-
That's a formalization for what we see when browsing a page. The JavaScript engine does nothing most of the time, it only runs if a script/handler/event activates.
20
+
Aceasta este o formalizare pentru ceea ce vedem atunci când navigăm pe o pagină. Motorul JavaScript nu face nimic în cea mai mare parte a timpului, se execută doar dacă se activează un script/gestionar/eveniment.
21
21
22
-
Examples of tasks:
22
+
Exemple de sarcini:
23
23
24
-
-When an external script `<script src="...">` loads, the task is to execute it.
25
-
-When a user moves their mouse, the task is to dispatch `mousemove`event and execute handlers.
26
-
-When the time is due for a scheduled `setTimeout`, the task is to run its callback.
27
-
- ...and so on.
24
+
-Atunci când se încarcă un script extern `<script src="...">`, sarcina este de a-l executa.
25
+
-Atunci când un utilizator își mișcă mouse-ul, sarcina este de a expedia evenimentul `mousemove`și de a executa gestionarii.
26
+
-Atunci când timpul este scadent pentru un `setTimeout` programat, sarcina este să ruleze callback-ul său.
27
+
- ...și așa mai departe.
28
28
29
-
Tasks are set -- the engine handles them -- then waits for more tasks (while sleeping and consuming close to zero CPU).
29
+
Sarcinile sunt setate -- motorul le gestionează -- apoi așteaptă mai multe sarcini (în timp ce doarme și consumă aproape zero CPU).
30
30
31
-
It may happen that a task comes while the engine is busy, then it's enqueued.
31
+
Se poate întâmpla ca o sarcină să vină în timp ce motorul este ocupat, atunci este pusă la coadă.
32
32
33
-
The tasks form a queue, so-called "macrotask queue" (v8 term):
33
+
Sarcinile formează o coadă, așa-numita "macrotask queue" (termen v8):
34
34
35
35

36
36
37
-
For instance, while the engine is busy executing a `script`, a user may move their mouse causing`mousemove`, and`setTimeout`may be due and so on, these tasks form a queue, as illustrated on the picture above.
37
+
De exemplu, în timp ce motorul este ocupat cu execuția unui `script`, un utilizator poate muta mouse-ul provocând`mousemove`, iar`setTimeout`poate fi scadent și așa mai departe, aceste sarcini formează o coadă, așa cum este ilustrat în imaginea de mai sus.
38
38
39
-
Tasks from the queue are processed on "first come – first served" basis. When the engine browser is done with the `script`, it handles `mousemove` event, then `setTimeout` handler, and so on.
39
+
Sarcinile din coadă sunt procesate în baza "primul venit -- primul servit". Atunci când motorul browserului a terminat cu `script`, acesta se ocupă de evenimentul `mousemove`, apoi gestionarul `setTimeout`, și așa mai departe.
40
40
41
-
So far, quite simple, right?
41
+
Până acum, destul de simplu, nu?
42
42
43
-
Two more details:
44
-
1.Rendering never happens while the engine executes a task. It doesn't matter if the task takes a long time. Changes to the DOM are painted only after the task is complete.
45
-
2.If a task takes too long, the browser can't do other tasks, such as processing user events. So after a time, it raises an alert like "Page Unresponsive", suggesting killing the task with the whole page. That happens when there are a lot of complex calculations or a programming error leading to an infinite loop.
43
+
Încă două detalii:
44
+
1.Randarea nu are loc niciodată în timp ce motorul execută o sarcină. Nu contează dacă sarcina durează mult timp. Modificările aduse la DOM sunt pictate numai după ce sarcina este finalizată.
45
+
2.Dacă o sarcină durează prea mult, browserul nu poate efectua alte sarcini, cum ar fi procesarea evenimentelor utilizatorului. Deci după un timp, acesta lansează o alertă ca "Page Unresponsive", sugerând uciderea sarcinii împreună cu întreaga pagină. Asta se întâmplă atunci când au loc o mulțime de calcule complexe sau când o eroare de programare duce la o buclă infinită.
46
46
47
-
That was the theory. Now let's see how we can apply that knowledge.
47
+
Aceasta a fost teoria. Acum să vedem cum putem aplica aceste cunoștințe.
48
48
49
-
## Use-case 1: splitting CPU-hungry tasks
49
+
## Cazul de utilizare 1: împărțirea sarcinilor flămânde de CPU
50
50
51
-
Let's say we have a CPU-hungry task.
51
+
Să presupunem că avem o sarcină flămândă de CPU.
52
52
53
-
For example, syntax-highlighting (used to colorize code examples on this page) is quite CPU-heavy. To highlight the code, it performs the analysis, creates many colored elements, adds them to the document -- for a large amount of text that takes a lot of time.
53
+
De exemplu, evidențierea sintaxei (utilizată pentru a colora exemplele de cod de pe această pagină) este destul de grea pentru CPU. Pentru a evidenția codul, se efectuează analiza, se creează multe elemente colorate, se adaugă la document - pentru o cantitate mare de text, ceea ce necesită mult timp.
54
54
55
-
While the engine is busy with syntax highlighting, it can't do other DOM-related stuff, process user events, etc. It may even cause the browser to "hiccup" or even "hang" for a bit, which is unacceptable.
55
+
În timp ce motorul este ocupat cu evidențierea sintaxei, nu poate face alte lucruri legate de DOM, procesa evenimentele utilizatorului etc. Poate chiar să provoace browserul să "sughițe" sau chiar să se "blocheze" pentru un timp, ceea ce este inacceptabil.
56
56
57
-
We can avoid problems by splitting the big task into pieces. Highlight first 100 lines, then schedule`setTimeout` (with zero-delay) for the next 100 lines, and so on.
57
+
Putem evita problemele împărțind sarcina mare în bucăți. Evidențiază primele 100 de rânduri, apoi programați`setTimeout` (cu întârziere zero) pentru următoarele 100 de rânduri, și așa mai departe.
58
58
59
-
To demonstrate this approach, for the sake of simplicity, instead of text-highlighting, let's take a function that counts from `1`to`1000000000`.
59
+
Pentru a demonstra această abordare, de dragul simplității, în loc de evidențierea textului, să luăm o funcție care numără de la `1`la`1000000000`.
60
60
61
-
If you run the code below, the engine will "hang" for some time. For server-side JS that's clearly noticeable, and if you are running it in-browser, then try to click other buttons on the page -- you'll see that no other events get handled until the counting finishes.
61
+
Dacă executați codul de mai jos, motorul se va "bloca" pentru o perioadă de timp. Pentru server-side JS acest lucru este clar vizibil, iar dacă îl executați în browser, atunci încercați să faceți clic pe alte butoane de pe pagină - veți vedea că niciun alt eveniment nu este gestionat până când numărătoarea se termină.
62
62
63
63
```js run
64
64
let i =0;
@@ -67,20 +67,20 @@ let start = Date.now();
67
67
68
68
functioncount() {
69
69
70
-
//do a heavy job
70
+
//face o treabă grea
71
71
for (let j =0; j <1e9; j++) {
72
72
i++;
73
73
}
74
74
75
-
alert("Done in"+ (Date.now() - start) +'ms');
75
+
alert("Terminat în"+ (Date.now() - start) +'ms');
76
76
}
77
77
78
78
count();
79
79
```
80
80
81
-
The browser may even show a "the script takes too long" warning.
81
+
Browserul poate chiar afișa un avertisment "the script takes too long".
82
82
83
-
Let's split the job using nested `setTimeout` calls:
83
+
Să împărțim sarcina folosind apeluri nested `setTimeout`:
84
84
85
85
```js run
86
86
let i =0;
@@ -89,37 +89,37 @@ let start = Date.now();
89
89
90
90
functioncount() {
91
91
92
-
//do a piece of the heavy job (*)
92
+
//face o parte din munca grea (*)
93
93
do {
94
94
i++;
95
95
} while (i %1e6!=0);
96
96
97
97
if (i ==1e9) {
98
-
alert("Done in"+ (Date.now() - start) +'ms');
98
+
alert("Terminat în"+ (Date.now() - start) +'ms');
99
99
} else {
100
-
setTimeout(count); //schedule the new call (**)
100
+
setTimeout(count); //programează noul apel (**)
101
101
}
102
102
103
103
}
104
104
105
105
count();
106
106
```
107
107
108
-
Now the browser interface is fully functional during the "counting" process.
108
+
Acum interfața browserului este complet funcțională în timpul procesului de "numărare".
109
109
110
-
A single run of `count`does a part of the job `(*)`, and then re-schedules itself`(**)`if needed:
110
+
O singură execuție a lui `count`face o parte din treabă `(*)`, și apoi se reprogramează`(**)`dacă este necesar:
111
111
112
-
1.First run counts: `i=1...1000000`.
113
-
2.Second run counts: `i=1000001..2000000`.
114
-
3. ...and so on.
112
+
1.Prima rulare numără: `i=1...1000000`.
113
+
2.A doua rulare numără: `i=1000001..2000000`.
114
+
3. ...și așa mai departe.
115
115
116
-
Now, if a new side task (e.g. `onclick` event) appears while the engine is busy executing part 1, it gets queued and then executes when part 1 finished, before the next part. Periodic returns to the event loop between `count`executions provide just enough "air" for the JavaScript engine to do something else, to react to other user actions.
116
+
Acum, dacă apare o nouă sarcină secundară (de exemplu, evenimentul `onclick`) în timp ce motorul este ocupat cu execuția părții 1, aceasta este pusă la coadă și apoi se execută când partea 1 s-a terminat, înainte de partea următoare. Revenirile periodice la event loop între execuțiile `count`oferă suficient "aer" pentru ca motorul JavaScript să facă altceva, să reacționeze la alte acțiuni ale utilizatorului.
117
117
118
-
The notable thing is that both variants -- with and without splitting the job by `setTimeout` -- are comparable in speed. There's not much difference in the overall counting time.
118
+
Lucrul notabil este că ambele variante -- cu și fără diviziunea muncii prin `setTimeout` -- sunt comparabile ca viteză. Nu există o diferență prea mare în timpul total pentru numărare.
119
119
120
-
To make them closer, let's make an improvement.
120
+
Pentru a le face mai apropiate, să facem o îmbunătățire.
121
121
122
-
We'll move the scheduling to the beginning of the`count()`:
122
+
Vom muta programarea la începutul lui`count()`:
123
123
124
124
```js run
125
125
let i =0;
@@ -128,43 +128,43 @@ let start = Date.now();
128
128
129
129
functioncount() {
130
130
131
-
//move the scheduling to the beginning
131
+
//mută programarea la început
132
132
if (i <1e9-1e6) {
133
-
setTimeout(count); //schedule the new call
133
+
setTimeout(count); //programează noul apel
134
134
}
135
135
136
136
do {
137
137
i++;
138
138
} while (i %1e6!=0);
139
139
140
140
if (i ==1e9) {
141
-
alert("Done in"+ (Date.now() - start) +'ms');
141
+
alert("Terminat în"+ (Date.now() - start) +'ms');
142
142
}
143
143
144
144
}
145
145
146
146
count();
147
147
```
148
148
149
-
Now when we start to `count()`and see that we'll need to `count()` more, we schedule that immediately, before doing the job.
149
+
Acum, când începem `count()`și vedem că va trebui să mai `count()`, programăm acest lucru imediat, înainte de a face treaba.
150
150
151
-
If you run it, it's easy to notice that it takes significantly less time.
151
+
Dacă o rulezi, este ușor de observat că durează semnificativ mai puțin timp.
152
152
153
-
Why?
153
+
De ce?
154
154
155
-
That's simple: as you remember, there's the in-browser minimal delay of 4ms for many nested `setTimeout` calls. Even if we set `0`, it's`4ms` (or a bit more). So the earlier we schedule it - the faster it runs.
155
+
Este simplu: după cum vă amintiți, există o întârziere minimă în browser de 4 ms pentru multe apeluri nested `setTimeout`. Chiar dacă setăm `0`, este`4ms` (sau un pic mai mult). Deci cu cât programăm mai devreme - cu atât mai repede se execută.
156
156
157
-
Finally, we've split a CPU-hungry task into parts - now it doesn't block the user interface. And its overall execution time isn't much longer.
157
+
În cele din urmă, am împărțit în părți o sarcină flămândă de CPU - acum nu blochează interfața cu utilizatorul. Iar timpul său total de execuție nu este cu mult mai mare.
158
158
159
-
## Use case 2: progress indication
159
+
## Cazul de utilizare 2: indicare de progres
160
160
161
-
Another benefit of splitting heavy tasks for browser scripts is that we can show progress indication.
161
+
Un alt beneficiu al împărțirii sarcinilor grele pentru scripturile din browser este că putem afișa indicarea progresului.
162
162
163
-
As mentioned earlier, changes to DOM are painted only after the currently running task is completed, irrespective of how long it takes.
163
+
Așa cum am menționat mai devreme, modificările aduse DOM sunt pictate numai după ce sarcina în curs de execuție este finalizată, indiferent cât de mult durează.
164
164
165
-
On one hand, that's great, because our function may create many elements, add them one-by-one to the document and change their styles -- the visitor won't see any "intermediate", unfinished state. An important thing, right?
165
+
Pe de o parte, asta e grozav, deoarece funcția noastră poate crea multe elemente, le adăugă unul câte unul în document și le modifică stilurile -- vizitatorul nu va vedea nici o stare "intermediară", neterminată. Un lucru important, nu-i așa?
166
166
167
-
Here's the demo, the changes to`i`won't show up until the function finishes, so we'll see only the last value:
167
+
Iată demonstrația, modificările aduse lui`i`nu vor apărea până când funcția nu se termină, așa că vom vedea doar ultima valoare:
168
168
169
169
170
170
```html run
@@ -183,11 +183,11 @@ Here's the demo, the changes to `i` won't show up until the function finishes, s
183
183
</script>
184
184
```
185
185
186
-
...But we also may want to show something during the task, e.g. a progress bar.
186
+
...Dar este posibil să dorim să afișăm ceva în timpul sarcinii, e.g. o bară de progres.
187
187
188
-
If we split the heavy task into pieces using `setTimeout`, then changes are painted out in-between them.
188
+
Dacă împărțim sarcina grea în bucăți folosind `setTimeout`, atunci modificările sunt pictate între ele.
189
189
190
-
This looks prettier:
190
+
Asta arată mai frumos:
191
191
192
192
```html run
193
193
<divid="progress"></div>
@@ -197,7 +197,7 @@ This looks prettier:
197
197
198
198
functioncount() {
199
199
200
-
//do a piece of the heavy job (*)
200
+
//să facă o parte din munca grea (*)
201
201
do {
202
202
i++;
203
203
progress.innerHTML= i;
@@ -213,25 +213,25 @@ This looks prettier:
213
213
</script>
214
214
```
215
215
216
-
Now the `<div>`shows increasing values of `i`, a kind of a progress bar.
216
+
Acum, `<div>`arată valorile crescânde ale lui `i`, un fel de bară de progres.
217
217
218
218
219
-
## Use case 3: doing something after the event
219
+
## Cazul de utilizare 3: a face ceva după eveniment
220
220
221
-
In an event handler we may decide to postpone some actions until the event bubbled up and was handled on all levels. We can do that by wrapping the code in zero delay `setTimeout`.
221
+
Într-un gestionar de evenimente putem decide să amânăm anumite acțiuni până când evenimentul a crescut și a fost gestionat la toate nivelele. Putem face asta prin ambalarea codului în `setTimeout` cu întârziere zero.
222
222
223
-
In the chapter <info:dispatch-events>we saw an example: custom event`menu-open`is dispatched in`setTimeout`, so that it happens after the "click" event is fully handled.
223
+
În capitolul <info:dispatch-events>am văzut un exemplu: evenimentul personalizat`menu-open`este expediat în`setTimeout`, astfel încât să se întâmple după ce evenimentul "click" a fost complet gestionat.
224
224
225
225
```js
226
226
menu.onclick=function() {
227
227
// ...
228
228
229
-
//create a custom event with the clicked menu item data
229
+
//crează un eveniment personalizat cu datele despre elementul de meniu pe care s-a făcut clic
230
230
let customEvent =newCustomEvent("menu-open", {
231
231
bubbles:true
232
232
});
233
233
234
-
//dispatch the custom event asynchronously
234
+
//expediază evenimentul personalizat în mod asincron
0 commit comments