Що робить postMessage() між потоками?
Що робить postMessage()
postMessage()- це метод, який дозволяє надіслати повідомлення з одного контексту в інший (наприклад, з основного потоку у Web Worker або навпаки).
Він не виконує прямого доступу до пам'яті, а передає копію даних - асинхронно, через механізм message passing (обмін повідомленнями).
Як це виглядає з Web Worker
Приклад
// main.js
const worker = new Worker('worker.js');
// Надсилаємо повідомлення воркеру
worker.postMessage({ task: 'sum', a: 5, b: 7 });
// Отримуємо відповідь
worker.onmessage = (event) => {
console.log('Відповідь від воркера:', event.data);
};// worker.js
onmessage = (event) => {
const { task, a, b } = event.data;
if (task === 'sum') {
postMessage(a + b); // надсилаємо результат назад
}
};Що відбувається:
- Основний потік викликає
worker.postMessage(...); - Повідомлення серіалізується і поміщається в чергу повідомлень воркера;
- У воркері спрацьовує подія
onmessage; - Воркер виконує обробку і відповідає через
postMessage(); - Основний потік ловить цю подію через
onmessage.
Усе це відбувається асинхронно - JavaScript не чекає, поки воркер відповість.
Що саме передається
Можна передавати:
- Примітиви (
string,number,boolean,null,undefined); - Об'єкти (JSON-сумісні);
ArrayBuffer,Blob,File,ImageBitmap;- Transferable об'єкти - передаються без копіювання.
Що таке Transferable Objects
Зазвичай дані копіюються під час передачі між потоками (через structured clone). Але для великих бінарних даних це дорого.
Transferable Objects (наприклад,
ArrayBuffer) можна "передати за посиланням"
- без копіювання, просто передавши володіння.
Приклад:
const buffer = new ArrayBuffer(1024);
worker.postMessage(buffer, [buffer]); // передаємо як transferableПісля передачі buffer в основному потоці стає невалідним (тому що "володіння" перейшло воркеру).
Це у 10-100 разів швидше при передачі великих даних.
Що повертає postMessage()
Нічого.
Він просто ставить повідомлення в чергу іншої сторони.
Отримувач зловить його через подію message:
worker.onmessage = (event) => {
console.log(event.data);
};Взаємодія в обидва боки
| Звідки | Метод | Слухач |
|---|---|---|
| Головний потік -> воркер | worker.postMessage() | onmessage у воркері |
| Воркер -> головний потік | postMessage() | worker.onmessage |
Приклад "луна" (echo worker)
// worker.js
onmessage = (event) => {
postMessage(`Луна: ${event.data}`);
};// main.js
worker.postMessage('Привіт!');
worker.onmessage = (e) => console.log(e.data);
// -> "Луна: Привіт!"postMessage() не тільки для Web Workers
Цей метод універсальний - він працює в різних контекстах браузера:
| Де використовується | Приклад |
|---|---|
| window -> iframe | iframe.contentWindow.postMessage(data, origin) |
| iframe -> parent | window.parent.postMessage(data, origin) |
| між вкладками | otherWindow.postMessage(data, origin) |
| Service Worker <-> Main | navigator.serviceWorker.controller.postMessage(data) |
| Web Worker <-> Main | worker.postMessage(data) |
Приклад: window.postMessage() між сторінками
// Сторінка А
const popup = window.open('https://example.com/popup.html');
popup.postMessage('Привіт, сторінко Б!', 'https://example.com');
// Сторінка Б
window.addEventListener('message', (event) => {
if (event.origin === 'https://example.com') {
console.log('Отримано повідомлення:', event.data);
}
});Дуже корисно для безпечної взаємодії між різними доменами (CORS-safe).
Як це влаштовано під капотом
- Коли викликається
postMessage(), дані серіалізуються за допомогою Structured Clone Algorithm; - Копія даних поміщається в чергу отримувача;
- Коли потік звільняється, браузер викликає обробник
onmessage(event); - Дані доступні в
event.data.
Що всередині event
onmessage = (event) => {
console.log(event.data); // самі дані
console.log(event.origin); // джерело (для вікон/iframe)
console.log(event.ports); // MessagePort, якщо є
console.log(event.source); // хто надіслав повідомлення
};Проста аналогія
Уяви, що postMessage() - це поштова служба між офісами.
Кожен офіс (потік JS) працює ізольовано.
Коли один хоче передати дані іншому,
він кладе лист (повідомлення) у скриньку (postMessage).
Інший офіс отримує лист, коли у нього є час (onmessage).
Підсумок
| Що робить | Пояснення |
|---|---|
postMessage() | Надсилає повідомлення між потоками / контекстами |
| Працює асинхронно | Не блокує код |
| Передає дані копією | Через structured clone |
| Оптимізація | Transferable об'єкти - без копіювання |
| Двосторонній зв'язок | Обидва потоки можуть надсилати і приймати |
| Використовується де | Web Workers, iframe, вікна, Service Workers |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.