Как стать автором
Обновить

Комментарии 6

Возможно стоит добавить что до Web Workers тяжёлые скрипты «деблокировались» другими средствами, например используя setTimeout(fn, 0). Несмотря на очевидную «костыльность» этого — перетаскивание кучи зависимостей в Worker на мой взгляд не сильно лучше.
Нет. setTimout — просто отсрочит выполнение скрипта (до тех пор пока не выполняться все синхронные вычисления), но потом fn всё равно будет выполняться в основном потоке, и «фризнет» страницу. В случае же с webworker, fn будет выполняться в отдельном потоке не влияющем на основной (собственно потому там нет доступа к dom и прочему окружению).
Там изначально расчёт идёт чтобы не «фризить» сразу на 3 секунды страницу одним куском, а синхронно проделав часть работы (допустим за 1/20 с) дать возможность другим сообщениям отработать, повесив остаток работы на «потом» и так 60 раз :).
Вместо одного большого фриза будет много маленьких фризят — но они конечным пользователем воспринимаются терпимее.
Worker выполняется в отдельном потоке, который создаёт браузер. То есть он выполняется паралельно, в другом «месте» и никак не тормозит основную страницу. Плюс этот поток сильно урезан в фичах, например там нет DOM, что делает его ещё более лёгким.
Удобнее все же workerScript не строкой хранить:

let workerFunctionString = function () {
    // тут можно использовать только глобальные функции
    
    let privateData = {
        // ...
    };

    function privateMethod() {
        // ...
    }

    onmessage = function (msg) {
        // пришел запрос от основного окна
        // ...
        postMessage({
            // ответ основному окну
            // ...
        });
    };

    // готов работать
    postMessage('ready');
}.toString();

let blobURL = URL.createObjectURL(new Blob(['(', workerFunctionString, ')()'], {type: 'application/javascript'}));

let myWorker = new Worker(blobURL);

URL.revokeObjectURL(blobURL);

let workerReadyCallback = function (message) {
    if (message.data === 'ready') {
        // воркер запустился
        removeEvent(myWorker, 'message', workerReadyCallback);

        myWorker.postMessage({
            // запускаем, что нужно
            // ...
        });
    }
};
addEvent(myWorker, 'message', workerReadyCallback);
Вот бы ещё сразу функцию в конструктор воркера отдавать, без блобов…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий