Пример использования Worker

Worker - технология JS, позволяющая запускать длительные вычисления в фоновом режиме. При этом страница браузера не "подвисает" и лишь время от времени обменивается с Worker-ом сообщениями, через которые передаются данные. Кроме этого, в большинстве браузеров, таймеры на неактивной странице тормозятся, что практически останавливает вычисления. С Worker-ом этого не происходит. Этот шаблон подготовлен для меня, но может оказаться полезным ещё кому-нибудь.

Простой пример

В код страницы вставляем:

let worker = new Worker("worker_simple.js");       // создаём Worker-а
 
worker.onmessage = function(e)                     // принимаем данные от worker
{
   switch(e.data.kind){                            // разновидность сообщения
      case "info":                                 // переписываемая информация о процессе
         document.getElementById("calcID").innerHTML = e.data.st;   
         break;
   }
};
 
worker.postMessage({kind:'start', number:10000000}); // посылаем данные в worker

Создаём файл "worker_simple.js" в котором помещаем:

'use strict';
if('function' === typeof importScripts) {         // подключаем внешние модули
//importScripts('queue.js');                      // должны быть, где и worker.js
}
var workerFinderSolution = new FinderSolution();
/****************************************************************************************
* Функция, получающая сообщения из внешнего управляющего модуля (html-страницы)
* e.data - содержит структуру данных, необходимых для вычислений
*/
onmessage = function(e)
{
   switch(e.data.kind){                           // разновидность сообщения
      case "start":                               // начало вычислений
         workerFinderSolution.number = e.data.number;
         workerFinderSolution.init ();            // инициализируем
         workerFinderSolution.timer();            // запускаем таймер
         break;
   }
}
/****************************************************************************************
*
*/
function FinderSolution()
{
   this.wait      = 1;                       // пауза в ms для получения сообщений
   this.send      = 100;                     // время в ms для послылки браузеру инфо  
   this.loops     = 1000;                    // число циклов вычислений до паузы
}
/****************************************************************************************
* Инициализация вычислений
*/
FinderSolution.prototype.init = function ()
{
   this.startTime = new Date();
}
/****************************************************************************************
* Условие окончания вычислений
*/
FinderSolution.prototype.finish = function ()
{
   return this.number <= 0;
}
/****************************************************************************************
* Один шаг вычислений
*/
FinderSolution.prototype.calc = function()
{
   this.number--;
}
/****************************************************************************************
* Таймерная функций
*/
FinderSolution.prototype.timer = function ()
{
   for(let i=0; !this.finish() && i < this.loops; i++)
      this.calc();                                // делаем loops циклов вычислений
 
   if((new Date() - this.startTime) > this.send){
      this.startTime = new Date();
      postMessage({kind:"info",  st:this.number });
   }
    
   if(!this.finish())                             // вызовем повторно через время wait
      setTimeout(this.timer.bind(this), this.wait);
   else                                           // вычисления окончились:
      postMessage({kind:"info",  st:"finish"});
}

Результаты вычисления: (перегрузите страницу)

Более продвинутый пример

number: , Нажми на меня


На html-странице есть два элемента для вывода с id="infoID" и id="outID". Первый служит для вывода частой (но короткой) информации о ходе вычислений (она всё время перетирается). Во второй, время от времени, добавляются промежуточные результаты вычислений. Запуск вычислений осуществляется нажатием кнопки run. Ею же можно вычисления прервать.

В данном примере число из поля редактирования передаётся в Worker. Там оно постоянно уменьшает на 1, пока не получит 0. Собственно вычисления находятся в модуле worker.js. Таймер на html-странице служит лишь для периодического запроса информации о ходе вычислений. Как страница, так и модуль worker.js подробно задокументированы, поэтому, для дальнейшего изучения технологии стоит переместиться в код.

Важное замечание. Если работа с Worker-ами происходит локально в Chrome, то необходимо закрыть все браузеры и запустить Chrome с ключом: --allow-file-access-from-files