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
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,7 +9,7 @@
9
9
10
10
## Событийный цикл
11
11
12
-
Идея *событийного цикла* очень проста. Есть бесконечный цикл, в котором движок JavaScript ожидает задачи, исполняет их, и снова ожидает появления новых.
12
+
Идея *событийного цикла* очень проста. Есть бесконечный цикл, в котором движок JavaScript ожидает задачи, исполняет их и снова ожидает появления новых.
13
13
14
14
Общий алгоритм движка:
15
15
@@ -34,14 +34,14 @@
34
34
35
35

36
36
37
-
Например, когда движок занят выполнением скрипта, пользователь может передвинуть мышь, тем самым вызвав появление события `mousemove`, или может истечь таймер, установленный `setTimeout` и т.п. Эти задачи формируют очередь, как показано на иллюстрации выше.
37
+
Например, когда движок занят выполнением скрипта, пользователь может передвинуть мышь, тем самым вызвав появление события `mousemove`, или может истечь таймер, установленный `setTimeout`, и т.п. Эти задачи формируют очередь, как показано на иллюстрации выше.
38
38
39
-
Задачи из очереди исполняются по правилу "первым пришел - первым ушёл". Когда браузер заканчивает выполнение скрипта, он обрабатывает событие `mousemove`, затем выполняет обработчик, заданный `setTimeout`, и так далее.
39
+
Задачи из очереди исполняются по правилу "первым пришёл - первым ушёл". Когда браузер заканчивает выполнение скрипта, он обрабатывает событие `mousemove`, затем выполняет обработчик, заданный `setTimeout`, и так далее.
40
40
41
41
Пока что всё просто, не правда ли?
42
42
43
43
Отметим две детали:
44
-
1. Рендеринг (отрисовка страницы) никогда не происходит во время выполнения задачи движком. Не имеет значение сколь долго выполняется задача. Изменения в DOM отрисовываются только после того, как задача выполнена.
44
+
1. Рендеринг (отрисовка страницы) никогда не происходит во время выполнения задачи движком. Не имеет значения, сколь долго выполняется задача. Изменения в DOM отрисовываются только после того, как задача выполнена.
45
45
2. Если задача выполняется очень долго, то браузер не может выполнять другие задачи, обрабатывать пользовательские события, поэтому спустя некоторое время браузер предлагает "убить" долго выполняющуюся задачу. Такое возможно, когда в скрипте много сложных вычислений или ошибка, ведущая к бесконечному циклу.
46
46
47
47
Это была теория. Теперь давайте взглянем, как можно применить эти знания.
@@ -54,7 +54,7 @@
54
54
55
55
Пока движок занят подсветкой синтаксиса, он не может делать ничего, связанного с DOM, не может обрабатывать пользовательские события и т.д. Возможно даже "подвисание" браузера, что совершенно неприемлемо.
56
56
57
-
Мы можем избежать этого, разбив задачу на части. Сделать подсветку для первых 100 строк, затем запланировать `setTimeout` (с нулевой задержкой) разметку следующих 100 строк, и т.д.
57
+
Мы можем избежать этого, разбив задачу на части. Сделать подсветку для первых 100 строк, затем запланировать `setTimeout` (с нулевой задержкой) для разметки следующих 100 строк и т.д.
58
58
59
59
Чтобы продемонстрировать такой подход, давайте будем использовать для простоты функцию, которая считает от `1` до `1000000000`.
60
60
@@ -160,11 +160,11 @@ count();
160
160
161
161
Ещё одно преимущество разделения на части крупной задачи в браузерных скриптах - это возможность показывать индикатор выполнения.
162
162
163
-
Обычно браузер отрисовывает содержимое страницы после того, как заканчивается выполнение текущего кода. Не имеет значения насколько долго выполняется задача. Изменения в DOM отображаются только после её завершения.
163
+
Обычно браузер отрисовывает содержимое страницы после того, как заканчивается выполнение текущего кода. Не имеет значения, насколько долго выполняется задача. Изменения в DOM отображаются только после её завершения.
164
164
165
165
С одной стороны, это хорошо, потому что наша функция может создавать много элементов, добавлять их по одному в документ и изменять их стили -- пользователь не увидит "промежуточного", незаконченного состояния. Это важно, верно?
166
166
167
-
В примере ниже, изменения `i` не будут заметны, пока функция не завершится, поэтому мы увидим только последнее значение `i`:
167
+
В примере ниже изменения `i` не будут заметны, пока функция не завершится, поэтому мы увидим только последнее значение `i`:
168
168
169
169
170
170
```html run
@@ -220,7 +220,7 @@ count();
220
220
221
221
В обработчике события мы можем решить отложить некоторые действия, пока событие не "всплывёт" и не будет обработано на всех уровнях. Мы можем добиться этого, обернув код в `setTimeout` с нулевой задержкой.
222
222
223
-
В главе <info:dispatch-events> мы видели пример: наше событие `menu-open` генерируется через `setTimeout`, чтобы возникло после того, как полностью обработано событие "click".
223
+
В главе <info:dispatch-events> мы видели пример: наше событие `menu-open` генерируется через `setTimeout`, чтобы оно возникло после того, как полностью обработано событие "click".
224
224
225
225
```js
226
226
menu.onclick=function() {
@@ -244,7 +244,7 @@ menu.onclick = function() {
244
244
245
245
Также есть специальная функция `queueMicrotask(func)`, которая помещает `func` в очередь микрозадач.
246
246
247
-
**Сразу после каждой *макрозадачи* движок исполняет все задачи из очереди *микрозадач* перед тем, как выполнить следующую макрозадачу или отобразить изменения на странице или сделать что-то ещё.**
247
+
**Сразу после каждой *макрозадачи* движок исполняет все задачи из очереди *микрозадач* перед тем, как выполнить следующую макрозадачу или отобразить изменения на странице, или сделать что-то ещё.**
248
248
249
249
Например:
250
250
@@ -267,11 +267,11 @@ alert("code");
267
267
268
268

269
269
270
-
**Все микрозадачи завершаются до обработки каких-либо событий или рендеринга или перехода к другой макрозадаче.**
270
+
**Все микрозадачи завершаются до обработки каких-либо событий или рендеринга, или перехода к другой макрозадаче.**
271
271
272
-
Это важно, так как гарантирует, что общее окружение остаётся одним и тем же между микрозадачами - не изменены координаты мыши, не получены новые данные по сети, и т.п.
272
+
Это важно, так как гарантирует, что общее окружение остаётся одним и тем же между микрозадачами - не изменены координаты мыши, не получены новые данные по сети и т.п.
273
273
274
-
Если мы хотели бы запустить функцию асинхронно (после текущего кода), но до отображения изменений и до новых событий, мы можем запланировать это через `queueMicrotask`.
274
+
Если бы мы хотели запустить функцию асинхронно (после текущего кода), но до отображения изменений и до новых событий, то мы могли бы запланировать это через `queueMicrotask`.
275
275
276
276
Вот пример с индикатором выполнения, похожий на предыдущий, но в этот раз использована функция `queueMicrotask` вместо `setTimeout`. Обратите внимание - отрисовка страницы происходит только в самом конце. Как и в случае обычного синхронного кода.
0 commit comments