awesome-everything EN
↑ Обратно к восхождению

Браузер и фронтенд-рантайм

Воркеры: чтение кода и сниппетов

Суть Читай реальные сниппеты воркера, postMessage и service worker — предскажи поведение во время выполнения или баг, потом выбери фикс с наибольшим рычагом, который сеньор делает первым.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 14 min

Баги воркеров прячутся на границе сообщений и в обработчике жизненного цикла, а не в алгоритме. Прочитай каждый сниппет, предскажи, что реально происходит на границе, и выбери фикс прежде, чем тянуться к профайлеру.

Цель

Отработай цикл, который ты гоняешь в каждом инциденте с воркером: прочитать вызов postMessage или обработчик жизненного цикла, найти скрытый clone-налог, или детачнутый буфер, или забытый waitUntil, и взять фикс с наибольшим рычагом.

Сниппет 1 — клон, который не переместился

// main.js — выносим тяжёлый фильтр изображения в воркер
const worker = new Worker('filter.js', { type: 'module' });
const pixels = new Uint8ClampedArray(width * height * 4); // ~32 МБ

worker.postMessage({ pixels, width, height });   // (A)
applyOtherUiWork();                                // (B) выполняется на ~32 мс позже
Викторина

Строка (B) выполняется примерно на 32 мс позже ожидаемого, хотя фильтр идёт в воркере. Что происходит на строке (A) и какой однострочный фикс?

Сниппет 2 — буфер, использованный после transfer

// main.js
const buf = new Float32Array(1_000_000);
fillSamples(buf);

worker.postMessage(buf, [buf.buffer]);   // передан через transfer
const sum = buf.reduce((a, x) => a + x); // (C) снова читает buf
Викторина

Что происходит на строке (C) и что это говорит о семантике transfer?

Сниппет 3 — install-обработчик, теряющий свой кэш

// sw.js
self.addEventListener('install', () => {
  caches.open('shell-v3').then(cache =>
    cache.addAll(['/index.html', '/app.4f3a1c.js'])
  );
});
Викторина

Под нагрузкой этот service worker иногда активируется с пустым или наполовину заполненным кэшем. В чём дефект и фикс?

Сниппет 4 — передача OffscreenCanvas

// main.js
const canvas = document.querySelector('#viz');
const offscreen = canvas.transferControlToOffscreen();
worker.postMessage({ offscreen }, [offscreen]);

// позже, на главном потоке:
const ctx = canvas.getContext('2d');   // (D)
ctx.fillRect(0, 0, 100, 100);          // (E)
Викторина

Воркер рендерит нормально, но строки (D)–(E) на главном потоке ведут себя неправильно. Что происходит и почему?

Итог

Каждый инцидент с воркером читается на границе, а не в алгоритме: postMessage крупного буфера по значению блокирует отправителя на синхронном structured clone — передавай ArrayBuffer через transfer; переданный буфер детачнут у отправителя — не читай его после (используй SharedArrayBuffer, если данные нужны обоим); install у service worker должен оборачивать асинхронное наполнение кэша в event.waitUntil, иначе воркер продвинется или умрёт рано; а transferControlToOffscreen делает владение canvas эксклюзивным, так что главный поток больше не рисует. Сначала читай обработчики сообщений и жизненного цикла — там и стоимость, и баги.

Продолжить восхождение ↑Воркеры: собери отзывчивый конвейер выноса работы
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.