JavaScript. Подробное руководство, 6-е издание, стр. 385

Пример 22.7. Обработка изображения в фоновом потоке выполнения

<b>// Получает объект ImageData от основного потока выполнения, обрабатывает его</b>

<b>// и отправляет обратно</b>

<b>onmessage = function(e) { postMessage(smear(e.data)); }</b>

<b>// Смазывает пикселы в ImageData вправо, воспроизводя эффект быстрого движения.</b>

<b>// При обработке больших изображений этой функции приходится выполнять огромный объем</b>

<b>// вычислений, что может вызвать эффект подвисания пользовательского интерфейса,</b>

<b>// если использовать ее в основном потоке выполнения.</b>

<b>function smear(pixels) {</b>

<b>  var data = pixels.data,</b>

<b>    width = pixels.width,</b>

<b>    height = pixels.height;</b>

<b>  var n = 10, m = n-1; // Нем больше n, тем сильнее эффект смазывания</b>

<b>  for(var row = 0; row &lt; height; row++) { // Для каждой строки</b>

<b>    var і = row*width*4 +4; // Индекс 2-го пиксела</b>

<b>    for(var col = 1; col &lt; width; col++, і += 4) { // Для каждого столбца</b>

<b>      data[i] = (data[i] + data[i-4]*m)/n;     // Красная составляющая</b>

<b>      data[i+1] = (data[i+1] + data[i-3]*m)/n; // Зеленая</b>

<b>      data[i+2] = (data[i+2] + data[i-2]*m)/n; // Синяя</b>

<b>      data[i+3] = (data[i+3] + data[i-1]*m)/n; // Альфа-составляющая</b>

<b>    }</b>

<b>  }</b>

<b>  return pixels;</b>

<b>}</b>

 Обратите внимание, что программный код в примере 22.7 может обрабатывать любое количество изображений, которые будут отправлены ему. Однако для простоты пример 22.6 создает новый объект

<b>Worker</b>
для обработки каждого изображения. Чтобы не плодить фоновые потоки, которые ничего не делают в ожидании новых сообщений, по завершении обработки изображения работа фонового потока завершается вызовом метода
<b>terminate().</b>

Следующий пример демонстрирует, как с помощью фоновых потоков выполнения можно писать синхронный программный код и безопасно использовать его в клиентских сценариях на языке JavaScript. В разделе 18.1.2.1 было показано, как с помощью объекта

<b>XMLHttpRequest</b>
выполнять синхронные НТТР-запросы, и говорилось, что такой способ его использования в основном потоке выполнения является не лучшим решением. Однако в фоновом потоке вполне оправданно выполнять синхронные запросы, и в примере 22.8 демонстрируется реализация фонового потока выполнения, которая выполняет именно такие запросы. Его обработчик события
<b>onmessage</b>
принимает массив URL-адресов, использует синхронный прикладной интерфейс объекта
<b>XMLHttpRequest</b>
для извлечения их содержимого и затем посылает полученное текстовое содержимое в виде массива строк обратно основному потоку выполнения. Или, если какой-либо HTTP-запрос потерпит неудачу, возбуждает исключение, которое распространится до обработчика
<b>onerror</b>
объекта
<b>Worker</b>
.

Отладка фоновых потоков выполнения

Одним из прикладных интерфейсов, недоступных в объекте

<b>WorkerGlobalScope</b>
(по крайней мере, на момент написания этих строк), является прикладной интерфейс доступа к консоли и одна из самых ценных его функций -
<b>console.log().</b>
Фоновые потоки не могут выводить текст в консоль и вообще не могут взаимодействовать с документом, поэтому их отладка может оказаться весьма трудным делом. Если фоновый поток возбудит исключение, основной поток получит событие «error» в объекте
<b>Worker</b>
. Но чаще бывает необходимо иметь в фоновом потоке хоть какой-нибудь способ выводить отладочные сообщения, которые будут видимы в веб-консоли броузера. Один из самых простых способов добиться этого - изменить протокол передачи сообщений, используемый для взаимодействия с фоновым потоком, чтобы он мог посылать отладочные сообщения. Так, в примере 22.6 можно было бы вставить следующий программный код в начало обработчика событий
<b>onmessage</b>
:

<b>if (typeof e.data === &quot;string&quot;) {</b>

<b>  console.log(&quot;Worker: &quot; + e.data):</b>

<b>  return:</b>

<b>}</b>

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

<b>postMessage()</b>
.

*******************************************

Пример 22.8. Выполнение синхронных HTTP-запросов в фоновом потоке

<b>// Этот файл будет загружен вызовом конструктора Worker(), поэтому он будет выполняться</b>

<b>// в независимом потоке выполнения и может безопасно использовать синхронный прикладной</b>

<b>// интерфейс объекта XMLHttpRequest. В качестве сообщения фоновому потоку должен</b>

<b>// передаваться массив URL-адресов. Поток синхронно извлечет содержимое</b>

<b>// из указанных адресов и вернет его в виде массива строк,</b>

<b>onmessage = function(e) {</b>

<b>  var urls = e.data; // Входные данные: URL-адреса извлекаемого содержимого</b>

<b>  var contents = []; // Выходные данные: содержимое указанных URL-адресов</b>

<b>  for(var і = 0: і &lt; urls.length; i++) {</b>