Большая часть содержания этого курса до сих пор была сосредоточена на таких концепциях, как общие соображения по производительности HTML, подсказки по ресурсам, оптимизация различных типов ресурсов для улучшения времени начальной загрузки страницы и реагирования на ввод пользователя, а также отложенная загрузка определенных ресурсов.
Однако есть один аспект производительности JavaScript, который еще не был рассмотрен в этом курсе, а именно роль веб-работников в улучшении скорости реагирования на ввод, которая рассматривается в этом и следующем модулях.
JavaScript часто описывают как однопоточный язык. На практике это относится к основному потоку , который представляет собой единственный поток, в котором браузер выполняет большую часть работы, которую вы видите в браузере. Эта работа включает в себя такие задачи, как написание сценариев, некоторые виды работы по рендерингу, анализ HTML и CSS, а также другие виды работы с пользователем, которая улучшает взаимодействие с пользователем. На самом деле браузеры используют другие потоки для выполнения работы, к которой вы, разработчик, обычно не имеете прямого доступа, например, потоки графического процессора .
Что касается JavaScript, вы обычно ограничены работой в основном потоке, но только по умолчанию. В JavaScript можно зарегистрировать и использовать дополнительные потоки. Функция, обеспечивающая многопоточность в JavaScript, известна как Web Workers API .
Веб-воркеры полезны, когда у вас есть дорогостоящая с точки зрения вычислений работа, которую просто невозможно выполнить в основном потоке, не вызывая при этом длительных задач, из-за которых страница не отвечает. Такие задачи, безусловно, могут повлиять на взаимодействие вашего веб-сайта с следующей отрисовкой (INP) , поэтому может быть полезно знать, когда у вас есть работа, которую можно выполнить полностью вне основного потока. Это может помочь освободить больше места для других задач в основном потоке и ускорить взаимодействие с пользователем.
Этот модуль и последующая демонстрация, показывающая конкретный вариант использования, охватывают веб-работников. Сама демонстрация показывает, как вы можете использовать веб-воркер для выполнения работы по чтению метаданных изображения из файла JPEG за пределами основного потока — и как вы можете вернуть эти метаданные обратно в основной поток, чтобы пользователь мог их увидеть.
Как запускается веб-воркер
Веб-воркер регистрируется путем создания экземпляра класса Worker
. При этом вы указываете, где находится код веб-рабочего, который браузер загружает и впоследствии создает для него новый поток. Результирующий поток часто называют рабочим потоком .
const myWebWorker = new Worker('/js/my-web-worker.js');
В файле JavaScript рабочего процесса (в данном случае my-web-worker.js
) вы можете затем написать код, который затем запускается в отдельном рабочем потоке.
Ограничения веб-работников
В отличие от JavaScript, который выполняется в основном потоке, у веб-работников нет прямого доступа к контексту window
. и иметь ограниченный доступ к предоставляемым API. На веб-работников распространяются следующие ограничения:
- Веб-работники не могут напрямую получить доступ к DOM.
- Веб-работники могут взаимодействовать с контекстом
window
через конвейер обмена сообщениями, а это означает, что веб-работник может каким-то образом косвенно обращаться к DOM. - Область веб-работника —
self
, а неwindow
. - Область веб-воркера имеет доступ к примитивам и конструкциям JavaScript, а также к API, таким как
fetch
и довольно большому количеству других API .
Как веб-работники разговаривают с window
Веб-работник может взаимодействовать с контекстом window
основного потока через конвейер обмена сообщениями. Этот конвейер позволяет пересылать данные в основной поток и веб-воркер и обратно. Чтобы отправить данные от веб-воркера в основной поток, вы настраиваете событие message
в контексте веб-воркера ( self
).
// my-web-worker.js
self.addEventListener("message", () => {
// Sends a message of "Hellow, window!" from the web worker:
self.postMessage("Hello, window!");
});
Затем в сценарии в контексте window
основного потока вы можете получить сообщение из рабочего веб-потока, используя еще одно событие message
:
// scripts.js
// Creates the web worker:
const myWebWorker = new Worker('/js/my-web-worker.js');
// Adds an event listener on the web worker instance that listens for messages:
myWebWorker.addEventListener("message", ({ data }) => {
// Echoes "Hello, window!" to the console from the worker.
console.log(data);
});
Конвейер обмена сообщениями веб-работника — это своего рода запасной выход из контекста веб-работника. С его помощью вы можете отправлять данные в window
из веб-воркера, который можно использовать для обновления DOM, или выполнять другую работу, которую необходимо выполнить в основном потоке.
Проверьте свои знания
В каком потоке работает веб-воркер?
К чему может получить доступ веб-работник?
window
, включая fetch
.window
, но только косвенно.Как веб-работник может получить доступ к контексту окна?
window
.window
.postMessage
в контексте веб-воркера ( self
).Далее: конкретный вариант использования веб-работника
В следующем модуле подробно описан и продемонстрирован конкретный вариант использования веб-работника. В этом модуле веб-воркер используется для получения файла JPEG по заданному URL-адресу и чтения его метаданных Exif в веб-воркере. Затем эти данные отправляются обратно в основной поток для отображения пользователю.