каталог
Чем отличается передок без закидывания от соленой рыбы?
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, работающий в фоновом режиме, независимый от других скриптов, и не влияющий на производительность страницы.
Может быть несколько очередей макрозадач и только одна очередь микрозадач.
задача макросавключать:
scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering
микрозадачивключать:
MutationObserverPromise.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/не…получено в.