каталог
Чем отличается передок без закидывания от соленой рыбы?
2 Предисловие
Event Loop
то есть цикл событий, что означает браузер илиNode
Механизм решения однопоточной среды выполнения JavaScript не будет блокироваться, то есть мы часто используем принцип асинхронности.
Три однопоточных и многопоточных
JavaScript — это однопоточный язык.
Когда один поток выполняет программу, пути программы, которые он использует, располагаются в последовательном порядке, первый должен быть хорошо обработан, а второй будет выполнен.
Взяв в качестве примера браузер Chrome, когда вы открываете вкладку, вы фактически создаете процесс.
В процессе может быть несколько потоков, например потоки рендеринга, потоки движка JS, потоки HTTP-запросов и т. д.
Когда вы инициируете запрос, вы фактически создаете поток, а когда запрос завершается, поток может быть уничтожен.
- Как выглядит ядро браузера?
Ядро браузера является многопоточным. Под управлением ядра потоки взаимодействуют друг с другом для поддержания синхронизации. Браузер обычно состоит из следующих резидентных потоков:
- Поток рендеринга графического интерфейса: анализировать HTML, CSS и т. д. Пока поток движка JavaScript выполняет сценарий, поток рендеринга GUI приостанавливается, то есть «замораживается».
- Поток движка JavaScript: отвечает за обработку сценариев JavaScript.
-
синхронизированный триггерный поток:
setTimeout
,setInterval
Ждать. Поток триггера событий добавит подсчитанные события в конец очереди задач и будет ждать выполнения потока JS-движка. - поток триггера события: Отвечает за передачу подготовленного события JS-движку для выполнения.
-
асинхронный
http
поток запросов: поток, отвечающий за выполнение таких функций, как асинхронные запросы, например.Promise.then()
,ajax
Ждать.
- Почему он не предназначен для многопоточности?
Предположим, естьDOM
Узел, есть темыA
работай, удали этоDOM
;
затем нитьB
Запустите его снова, измените этоDOM
какая-то часть.
Итак, теперь вопрос в том, кого мы слушаем?
Таким образом, он просто разработан как единый поток, который безопасен и надежен.
Даже если HTML5 выйдет позжеWeb Worker
операция не разрешенаDOM
Структура, может завершить некоторые распределенные вычисления.
Web Worker
объясняется в этой статье
- Зачем вам асинхронность?
На этот раз есть другая проблема.Если вызвать интерфейс (Ajax
), или при загрузке изображения мы застреваем, поэтому страница не может отображаться все время?
Затем, поскольку один поток может позволить предыдущей программе завершиться первой, даже если интерфейс или изображение замедляются, у меня все еще есть другие задачи, которые я не выполнил.
Так что это время приходит асинхронно:
Когда дело доходит до некоторых операций, требующих ожидания, мы разрешаем программе продолжать работу.
Дождавшись возвращения интерфейса или картинки, я уведомлю программу о том, что закончил, и можно продолжать звонить.
Цикл четырех событий
- Почему есть контур событий?
ПереднийjsliangК слову о: потоки JavaScript могут выполнять только одно действие за раз.
Если вы столкнулись с некоторыми программами, которые должны ждать, например,setTimeout
Подождите, давайте остановимся.
Итак, чтобы координировать события, взаимодействие с пользователем, сценарии, рендеринг, работу в сети и т. д., JavaScript придумалЦикл событий.
- Что такое петля событий?
JavaScript изscript
Процесс чтения событий выполнения из «очереди задач» начинает читать, а затем непрерывно зацикливается, чтоЦикл событий.
4.1 Процесс выполнения цикла событий
Event LoopПроцесс выполнения следующий:
- Запустить весь скрипт
script
Выполнить как задачу макроса - Во время выполнения,синхронный кодвыполнять напрямую,задача макросаВойдите в очередь задач макроса,микрозадачиВойдите в очередь микрозадач.
- После того, как текущая задача макроса будет выполнена и удалена из очереди, проверьте список микрозадач и выполняйте их последовательно, пока все выполнения не будут завершены.
- Запустите браузер
UI
Работа с потоковым рендерингом. - Проверить
Web Worker
задачи, выполнять их. - После выполнения этого цикла макрозадач вернитесь к шагу 2 и выполняйте цикл по очереди, пока очереди макрозадач и микрозадач не опустеют.
В цикле событий есть два вида асинхронных очередей: очередь макрозадач (MacroTask
) и очередь микрозадач (MicroTask
).
Web Worker — это JS, работающий в фоновом режиме, независимый от других скриптов, и не влияющий на производительность страницы.
Может быть несколько очередей макрозадач и только одна очередь микрозадач.
задача макросавключать:
script
setTimeout
setInterval
setImmediate
I/O
UI rendering
микрозадачивключать:
MutationObserver
Promise.then()/catch()
- к
Promise
Другие технологии, разработанные для базы, такие какfetch API
- Процесс сборки мусора в V8
- Уникальный для узла
process.nextTick
4.2 requestAnimationFrame
4.2.1 Введение в requestAnimationFrame
window.requestAnimationFrame()
Сообщите браузеру, что вы хотите выполнить анимацию, и попросите браузер вызвать указанную функцию обратного вызова, чтобы обновить анимацию перед следующей перерисовкой.
Этот метод должен передать функцию обратного вызова в качестве параметра, функция обратного вызова будет выполнена до следующей перерисовки браузера.
requestAnimationFrame
короткое имяrAF
.
Давайте посмотрим на его использование:
<body>
<div class="animation">动画元素</div>
<script>
window.onload = function() {
const element = document.querySelector('.animation');
let start;
function step(timestamp) {
if (start === undefined) {
start = timestamp;
}
const elapsed = timestamp - start;
// 这里使用 Math.min() 确保元素刚好停在 200px 的位置。
element.style.transform = 'translateX(' + Math.min(0.1 * elapsed, 200) + 'px)';
// 在两秒后停止动画
if (elapsed < 2000) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
};
</script>
</body>
4.2.2 Причина использования requestAnimationFrame
если мы используемsetTimeout
Чтобы добиться эффекта анимации, мы обнаружим, что на некоторых недорогих машинах возникает явление заикания и дрожания, Причины этого:
-
setTimeout
Событие выполнения не является детерминированным. Он принадлежит очереди задач макроса.Только когда задачи в основном потоке выполняются, задачи в очереди будут вызываться, чтобы определить, начинать ли выполнение. - На частоту обновления влияет разрешение экрана и размер экрана, поэтому разные устройства имеют разную частоту обновления, в то время как
setTimeout
Только фиксированный интервал времени может быть обновлен.
наверхуEvent Loop
Во время процесса мы знаем, что после выполнения очереди микрозадач будет один шаг:
- Запустите браузер
UI
Работа с потоковым рендерингом.
а такжеrequestAnimationFrame
Просто выполните его здесь, вы не будете ждать очереди очереди задач макроса, что вызовет такие проблемы, как зависание.
4.3 Web Worker
Web Worker
Предоставляет простой способ запуска сценариев в фоновом потоке для веб-контента.
Как мы знаем, JavaScript всегда был однопоточной средой, и мы не можем запускать два JavaScript-скрипта одновременно.
Но представьте, если бы мы могли запускать два (или более) сценария JavaScript одновременно, один для обработки пользовательского интерфейса (как он всегда использовался), а другой для обработки некоторых сложных вычислений, тогда производительность была бы лучше.
В новой спецификации HTML5 реализованоWeb Worker
Чтобы представить технологию «многопоточности» JavaScript, ее способность позволяет нам загружать и запускать еще один отдельный поток JavaScript в потоке JavaScript, работающем на главной странице.
Примечание. JavaScript по своей природе является однопоточным.
Web Worker
Просто мощный API, предоставляемый браузером (средой хостинга).
4.3.1 Использование веб-воркера
Вызвать веб-воркера:
index.js
console.log('index-同步任务');
Promise.resolve().then((res) => {
console.log('index-Promise');
});
setTimeout(() => {
console.log('index-setTimeout');
}, 1000);
index.html
<script>
window.onload = function() {
console.log('本地-同步任务');
// 微任务之间
Promise.resolve().then((res) => {
console.log('本地-微任务 1');
})
const worker1 = new Worker('./index.js');
Promise.resolve().then((res) => {
console.log('本地-微任务 2');
})
// 宏任务之间
setTimeout(() => {
console.log('本地-宏任务 1');
}, 1000);
const worker2 = new Worker('./index.js');
setTimeout(() => {
console.log('本地-宏任务 2');
}, 1000);
};
</script>
Распечатайте результат при выполнении:
本地-同步任务
本地-微任务 1
本地-微任务 2
index-同步任务
index-Promise
index-同步任务
index-Promise
本地-宏任务 1
本地-宏任务 2
index-setTimeout
index-setTimeout
можно увидеть:
- выполнить первым
script
промежуточная задача синхронизации - повторно выполнить
script
Средние и микро задачи - Затем выполните работу по рендерингу UI-потока (в коде это не отражено, если интересно, можете попробовать добавить
rAF
) - затем выполнить
Web Worker
внутреннее содержимое - тогда снова
index.html
задача макроса в - Ну наконец то
Web Worker
Макросправки в файлах
Видно, что он по-прежнему соответствуетEvent Loop
обработать.
4.3.2 Передача данных веб-воркера
index.js
onmessage = (res) => {
// Worker 接收数据
console.log('Worker 收到数据:', res);
// Worker 收到数据:
// MessageEvent {isTrusted: true, data: "查房,这里是 index.html!", origin: "", lastEventId: "", source: null, …}
// Worker 发送数据
postMessage('开门!这里是 index.js');
}
index.html
<script>
window.onload = function() {
// 实例化 Worker
const worker = new Worker('./index.js');
// index.html 接收数据
worker.addEventListener('message', (res) => {
console.log('index.html 收到数据:', res);
// index.html 收到数据:
// MessageEvent {isTrusted: true, data: "开门!这里是 index.js", origin: "", lastEventId: "", source: null, …}
});
// index.html 发送数据
worker.postMessage('查房,这里是 index.html!');
// 终止 Worker
worker.terminate();
};
</script>
существуетindex.html
, через:
-
worker.addEventListener('message', callback)
. Получение данных, переданных Web Worker. -
worker.postMessage('xxx')
. Отправьте данные в Web Worker. -
worker.terminate()
. Завершить общение
существуетindex.js
, через:
onmessage = (res) => {
console.log(res); // 在 onmessage 方法接受数据
postMessage('xxx'); // 通过 postMessage 发送数据
}
4.3.3 Активный API веб-воркера
-
setTimeout(), clearTimeout(), setInterval(), clearInterval()
: С помощью этих функций вы можетеWeb Worker
Операция синхронизации выполняется в потоке; -
XMLHttpRequest
Объект: означает, что мы можемWeb Worker
выполнить в потокеAjax
просить; -
navigator
объект: доступенppName
,appVersion
,platform
,userAgent
и другая информация; -
location
Объект (только для чтения): можно получить информацию о текущем URL-адресе;
Если вам нужно загрузить другие JS-скрипты:
importScripts('./index2.js', './index3.js');
// 或者
// importScripts('./index2.js');
// importScripts('./index3.js');
4.3.4 Совместимость веб-воркеров
- IE: версия 11
- Грань: Версия 14+
- Firefox: версия 51+
- Хром: версия 56+
- Другое: см.ссылка на канал
4.4 Узел и браузер
почему бы не бытьЦикл событий браузераа такжеNode.js Event Loop?
Проще говоря:
- Ваша страница отображается в браузере, а ваши данные обрабатываются в фоновом режиме (представьте себе Node.js как внутренний язык, такой как PHP и Java). Есть ли разница между ними? !
Чуть осторожнее:
-
Node.js: Node.js
Event Loop
основывается наlibuv
.libuv
Уже на Node.jsEvent Loop
осуществленный. -
браузер: браузер
Event Loop
основывается наСпецификация HTML5из. Спецификация HTML5 определяет толькоEvent Loop
Конкретная реализация остается на усмотрение производителя браузера.
libuv
— это многоплатформенная библиотека поддержки, в основном используемая для асинхронного ввода-вывода. Первоначально он был разработан для Node.js, а теперьLuvit
,Julia
,pyuv
и другие фреймворки также используют его.Github — репозиторий libuv
Итак, мы должны объединить эти дваEvent Loop
Различай их, это разные вещи~
5 Сравнение двух циклов событий окружающей среды
В среде браузераmicrotask
Очередь задачmacrotask
Выполнить после выполнения.
В то время как в Node.jsmicrotask
Он будет выполняться между различными этапами цикла событий, то есть после выполнения этапа он будет выполнятьсяmicrotask
Очередь задач.
Механизм временного цикла Node.js здесь не упоминается.jsliangЯ не знаком с Node и боюсь ввести в заблуждение; во-вторых, когда интервьюер спрашивает, он в основном отвечает механизму цикла событий браузера и иногда упоминает об этом.Event Loop
Разделенный на цикл событий браузера и цикл событий узла, это небольшая точка.
Обучение по шести темам
Перед обучением поговорим об объеме тестовых вопросов:
- Синхронизировать задачу: В случае прямого исполнения не беспокойтесь о 3721.
-
задача макроса:
script
,setTimeout
-
микрозадачи:
Promise.then()
,async/await
На этом пока все, не могу ошибиться!
6.1 Задачи синхронизации
function bar() {
console.log('bar');
}
function foo() {
console.log('foo');
bar();
}
foo();
Каков результат этого контента?
-
foo
->bar
Детали объяснять не нужно.
6.2 Таймер
console.log("1");
setTimeout(function () {
console.log("2");
}, 0);
setTimeout(function () {
console.log("3");
}, 2000);
console.log("4");
- Очередь задач макроса:
script
,setTimeout(2)
,setTimeout(3)
- Очередь микрозадач: нет
Итак, вывод:
1
4
2
3
6.3 Таймер + Обещание
- Вопрос 1: Пожалуйста, выведите следующий код.
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
script
Под задачей макроса:
- задача макроса
setTimeout
- микрозадачи
.then(promise1)
Поэтому сначала выполните синхронный код, сначала выведите:script start
-> script end
.
Затем вызовите микрозадачу, выводpromise1
,Будуthen(promise2)
Ставьте микрозадачи.
Снова вызовите микрозадачу, поставивpromise2
выход.
Наконец, вызов макросаsetTimeout
, выходsetTimeout
.
Итак, порядок вывода:
script start
script end
promise1
promise2
setTimeout
- Вопрос 2: Пожалуйста, выведите следующий код.
Promise.resolve().then(function promise1() {
console.log('promise1');
})
setTimeout(function setTimeout1() {
console.log('setTimeout1')
Promise.resolve().then(function promise2() {
console.log('promise2');
})
}, 0)
setTimeout(function setTimeout2() {
console.log('setTimeout2')
}, 0)
script
Под задачей макроса:
- Задача синхронизации: нет
- Микрозадачи:
Promise.then(promise1)
- Задача макроса:
setTimeout(setTimeout1)
,setTimeout(setTimeout2)
Так что сначала зайдите в задачу синхронизации, обнаружите, что ее нет, проигнорируйте.
Затем перейдите к микрозадачамPromise.then(promise1)
, выходpromise1
.
Затем запустите задачу макроса, сначалаsetTimeout(setTimeout1)
:
- Синхронизация задач:
console.log('setTimeout1')
- Микрозадачи:
Promise.then(promise2)
- Задача макроса:
setTimeout(setTimeout2)
(обратите внимание, что задача макроса здесь целостная)
Итак, сначала перейдите к задаче синхронизации, выведитеsetTimeout1
.
Затем переходим к микрозадаче и выводимpromise2
.
Затем запустите задачу макросаsetTimeout(setTimeout2)
.
setTimeout(setTimeout2)
В среде отсутствуют микрозадачи и макрозадачи, поэтому после выполнения задачи синхронизации выведитеsetTimeout2
, все кончено.
Итак, порядок вывода:
promise1
setTimeout1
promise2
setTimeout2
- Вопрос 3: Пожалуйста, выведите следующий код.
setTimeout(function() {
console.log(4);
}, 0);
const promise = new Promise((resolve) => {
console.log(1);
for (var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(2);
}).then(function() {
console.log(5);
});
console.log(3);
script
Вниз:
- Синхронизация задач:
console.log(1)
,console.log(2)
,console.log(3)
. - Микрозадачи:
Promise.then()
(Подождите до 9999, чтобы добавить его) - задача макроса
setTimeout
Итак, давайте сначала перейдем к задаче синхронизации, обратите внимание, когда мыnew Promsie()
, внутренний код будет выполняться так же, как и синхронная задача, и.then()
существуетresolve()
добавляется в микрозадачу.
Итак, выведите сначала1 -> 2 -> 3
.
Затем запускайте микрозадачиPromise.then()
, поэтому выведите 5.
Наконец, запустите задачу макросаsetTimeout
, выход 4.
Последовательность результатов такова:
1
2
3
5
4
6.4 Общие
Комплексный вопрос не будет анализироваться для ответа, пожалуйста, решите сами.
- Вопрос 1: Пожалуйста, выведите следующий код.
setTimeout(function () {
console.log('timeout1');
}, 1000);
console.log('start');
Promise.resolve().then(function () {
console.log('promise1');
Promise.resolve().then(function () {
console.log('promise2');
});
setTimeout(function () {
Promise.resolve().then(function () {
console.log('promise3');
});
console.log('timeout2')
}, 0);
});
console.log('done');
результат:
start
done
promise1
promise2
timeout2
promise3
timeout1
- Вопрос 2: Пожалуйста, выведите следующий код.
console.log("script start");
setTimeout(function() {
console.log("setTimeout---0");
}, 0);
setTimeout(function() {
console.log("setTimeout---200");
setTimeout(function() {
console.log("inner-setTimeout---0");
});
Promise.resolve().then(function() {
console.log("promise5");
});
}, 200);
Promise.resolve()
.then(function() {
console.log("promise1");
})
.then(function() {
console.log("promise2");
});
Promise.resolve().then(function() {
console.log("promise3");
});
console.log("script end");
выход:
script start
script end
promise1
promise3
promise2
setTimeout---0
setTimeout---200
promise5
inner-setTimeout---0
- Вопрос 3: Пожалуйста, выведите следующий код.
console.log(1);
setTimeout(() => {
console.log(2);
new Promise((resolve) => {
console.log(3);
}).then(() => {
console.log(4);
});
}, 200);
new Promise((resolve) => {
console.log(5);
resolve();
}).then(() => {
console.log(6);
});
setTimeout(() => {
console.log(7);
}, 0);
setTimeout(() => {
console.log(8);
new Promise(function (resolve) {
console.log(9);
resolve();
}).then(() => {
console.log(10);
});
}, 100);
new Promise(function (resolve) {
console.log(11);
resolve();
}).then(() => {
console.log(12);
});
console.log(13);
выход:
1
5
11
13
6
12
7
8
9
10
2
3
7 ссылок
- В чем разница между браузером и циклом событий Node?【Рекомендация по прочтению: 20 минут】
- Понимание цикла событий за раз (тщательно решайте такие вопросы интервью)【Рекомендация по прочтению: 20 минут】
- Эти вещи о механизме цикла событий【Рекомендация по прочтению: 10 минут】
- Глубокое понимание механизма цикла событий js (Node.js)[Рекомендация по прочтению: нет]
- Подробно объясните механизм цикла событий в JavaScript.【Рекомендация по прочтению: 5 минут】
- Глубокое понимание петли событий JavaScript【Рекомендация по прочтению: 20 минут】
- [ПОСЛЕДНИЙ РАЗ] Тщательно изучите механизм выполнения JavaScript【Рекомендация по прочтению: 20 минут】
- JavaScript: глубокое понимание синхронизации, асинхронности и цикла событий.【Рекомендация по прочтению: 10 минут】
- Изучите время асинхронного рендеринга javaScript и обновления браузера из спецификации цикла событий.【Рекомендация по прочтению: 20 минут】
- Tasks, microtasks, queues and schedules[Рекомендация по прочтению: нет]
- The Node.js Event Loop, Timers, and process.nextTick()[Рекомендация по прочтению: нет]
7.1 Ссылки requestAnimationFrame
- Поговорим о Promise, setTimeout, rAF, rIC【Рекомендация по прочтению: 10 минут】
- window.requestAnimationFrame【Рекомендация по прочтению: 10 минут】
7.2 Ссылки на веб-воркеров
- Многопоточность в JavaScript -- Web Workers【Рекомендация по прочтению: 30 минут】
- Говоря о веб-воркере HTML5【Рекомендация по прочтению: 10 минут】
- Инструмент производительности JavaScript — Web Worker【Рекомендация по прочтению: 10 минут】
7.3 Другие ссылки
- процесс браузера? нить? тупо не могу сказать!【Рекомендация по прочтению: 5 минут】
репозиторий документации jsliang предоставляетсяЛян ЦзюньронгиспользоватьCreative Commons Attribution-NonCommercial-ShareAlike 4.0 Международная лицензияЛицензия.
на основеGitHub.com/l ian Jun Ron…Создание работ выше.
Права на использование, отличные от разрешенных в настоящем Лицензионном соглашении, могут быть получены отCreative Commons.org/licenses/не…получено в.