Това е съвет, който много разработчици следват, защото браузърът работи с единичен основен поток, който обслужва критични задачи като визуализация (rendering) и обработка на входни събития. За да се гарантира плавността и отзивчивостта на уеб приложенията, тежките изчисления и обработките често се прехвърлят в отделни работни процеси (background workers), с което се постига строга разделеност между потребителския интерфейс (UI) и изчислителната част.
Основният поток в браузъра е еднопоточен, а той се грижи за няколко критично важни неща — рендиране на страницата, отговаряне на действия на потребителя (клик, скрол и др.) и изпълнение на JavaScript. Ако основной поток бъде блокиран с тежка задача, цялото приложение „замръзва“ или реагира с голямо закъснение, което нарушава потребителското преживяване.
Ето защо идеята е: ако имате тежка или CPU-интензивна работа, по-добре е да я изнесете в отделен работен процес (например Web Worker), който работи паралелно и така основният поток остава свободен и отзивчив.
По време на разработката на разширение за Chrome, наречено Fastary, което разполага с функциите за правене на екранни снимки (screenshots), авторът се сблъсква със забавяне и интуитивна тромавост.
Първоначално, архитектурата беше изградена така, че основните canvas операции се изпълняват в Offscreen Document — вид background процес, през който се прехвърлят големи изображения (например Base64 кодирани картинки). Въпреки този подход задължително имаше 2–3-секундно забавяне, при което направата на скрийншот се усещаше като бавна.
Причината? Цената на сериализация, копиране и десериализация на големи обеми данни между отделните контексти на браузъра. Важно е да се знае, че всеки контекст (основен поток, Web Worker, Service Worker, скриптове на разширения) работи в изолирана памет и себеизолира се от останалите. За комуникация между тях се използва API като postMessage(), което разчита на Structured Clone Algorithm (SCA).
SCA прави дълбоко копие (deep clone) на обекта — процес, който е синхронен и изцяло блокира основния поток по време на изпълнението си. Колкото по-големи са данните, толкова повече време отнема сериализацията и копирането — и този разход расте линейно с размера.
Например, при прехвърляне на изображение с няколко мегабайта от един контекст в друг, интерфейсът може да замръзне, докато SCA сериализира съдържанието.
Съществуват и Transferable обекти, като ArrayBuffer, при които вместо копиране се прехвърля собствеността върху ресурса между контекстите. Това позволява значително по-бързо предаване на данни без блокиране.
Обаче, в някои случаи (например при някои сценарии за изпращане на съобщения в разширения за Chrome) Transferable обекти не са използваеми, така че разработчиците трябва да разчитат на класическата сериализация, която е сравнително бавна.
Връщайки се към примерa с Fastary, създателят осъзнава, че чистото правило „не блокирай основния поток“ не е универсално валидно. По-правилно е да се казва: „Не блокирай основния поток за прекалено дълго време“, защото ако цената на прехвърляне на данни между контекстите (сериализация + десериализация) е по-голяма от времето на обработка на данните на самия основен поток, тогава изнасянето на задачата в работен процес изглежда по-неефективно.
Fastary първоначално изпълняваше скрийншота в background worker, след което прехвърляше голямото изображение към Offscreen Document за обработка и връщаше резултата обратно. Това означаваше два пъти тежка сериализация на много големи обекти.
На Retina дисплеи размерът на изображението и броят пиксели са много по-големи, а дори се появиха проблеми с неправилно изрязване на картинките заради несъвпадение между CSS и физическите пиксели (фактор devicePixelRatio).
Решението беше да се премести обработката директно в основния поток, в content script, където обработката и мащабирането се извършваха без трансфери на данни. Въпреки че основният поток беше „блокиран“ за кратък период, общата забавяне се сви и потребителското изживяване беше по-гладко и отзивчиво, особено при Retina устройства.
Eто един преглед на взетите поуки:
Общо взето, времето за пълното изпълнение — сериализация, предаване, обработка и десериализация — трябва да се разглежда като цяло. Ако прехвърлянето е по-бавно от изчисленията, изолиране на задачи в отделни контексти може да бъде дори задълбочаващ бъг.
Правилото „никога не блокирай основния поток“ е добро ръководство, но изисква нюансиране според конкретните характеристики на задачата. Разработчиците трябва да измерват и съпоставят времето за прехвърляне на данни и времето за обработка. На тази база да вземат решение каква архитектура да приложат — дали да раздробят процеса в работни потоци, или да извършат обработката локално.
По този начин се постига оптимален баланс между производителност, отзивчивост и сложност на кода, което е ключово за създаване на модерни уеб приложения и разширения с отличен потребителски опит.
Песимистична прогноза за Биткойн: Възможен върхов импулс до $150К и последващ спад до $3-4К
SЕО Новини: Ноември 2025 г.
12 любими нови филма от 2025: от 'Анора' до приключения с дълбоки послания