Статьи

Работа с Inline Web Workers


В прошлом я писал пост о том, что такое
веб-работники . Короче говоря, Web Workers позволяют веб-разработчикам запускать код JavaScript в фоновом режиме, что может помочь повысить производительность веб-страницы. Эта статья расскажет, что такое встроенные веб-работники и как их создавать.

Встроенные веб-работники

При работе с веб-работниками в большинстве случаев вы создаете отдельный файл JavaScript для выполнения работником. Встроенные веб-работники — это веб-работники, которые создаются в том же контексте веб-страницы или на лету. Причина для этого очевидна: иногда мы хотим уменьшить количество запросов, выполняемых страницей, а иногда нам нужно создать некоторые функциональные возможности на лету. Выполнение внешних файлов JavaScript не может помочь нам в этом.

Существует два вида встроенных веб-работников:

  • Page inline worker — код JavaScript работника создается встроенным внутри веб-страницы. В этом случае вы будете использовать тег script с идентификатором и типом javascript / worker. тип укажет браузеру не анализировать написанный встроенный JavaScript и будет ссылаться на него как на строку. Вот пример для такого тега скрипта: 
  • <script id="worker" type="javascript/worker">
       postMessage('worker sent message');
    </script>
    

     Позже вы сможете извлечь скрипт по его идентификатору и использовать его свойство textContent для извлечения рабочего тела.

  • На лету работника — код JavaScript работника предоставляется из внешнего источника в виде строки.

В обоих случаях для запуска работника вам потребуется создать объект BLOB-объекта и URL-адрес BLOB-объекта.

Создание веб-работника

Основным способом создания встроенного веб-работника является использование объекта BlobBuilder, который был добавлен файловым API HTML5 . BlobBuilder позволяет создать объект блоб из заданной строки. Он включает в себя две основные функции — функцию добавления и функцию getBlob . Функция append добавляет данные в подчеркивающий BLOB-объект, а getBlob возвращает созданный объект BLOB-объекта.

После того, как вы создадите объект BLOB из встроенной рабочей реализации, вам нужно будет создать из него URL. Причина в том, что Web Workers получает URL в качестве параметра. Для нашего спасения HTML5 определяет еще две функции в File API — createObjectURL и revokeObjectURL . Обе функции существуют в объекте window.URL . URL-адреса BLOB-объектов — это уникальные URL-адреса, которые создаются и сохраняются браузером вплоть до выгрузки документа. Функция createObjectURL получает объект BLOB-объекта и возвращает URI BLOB-объекта, который можно использовать. Функция revokeObjectURL используется для освобождения созданного URL-адреса BLOB- объекта . Если вы создаете много URL-адресов BLOB-объектов, вы должны использовать revokeObjectURL чтобы освободить ссылки на неиспользуемые URL-адреса BLOB-объектов

Давайте рассмотрим пример создания встроенного веб-работника:

var bb = new BlobBuilder();
bb.append(workerBody);
var workerURL = window.URL.createObjectURL(bb.getBlob());
var worker = new Worker(workerURL);

В этом примере создается BlobBuilder и к нему добавляется workerBody. WorkerBody может быть любым фрагментом кода, который вы хотите запустить внутри Web Worker. После создания блоба в памяти вы будете использовать функцию createObjectURL, чтобы создать URL-адрес блоба и использовать его в качестве параметра для веб-рабочего. Если вы хотите использовать тег script из первого примера кода, вы можете написать следующий код:

var bb = new BlobBuilder();
bb.append(document.querySelector('#worker').textContent);
var workerURL = window.URL.createObjectURL(bb.getBlob());
var worker = new Worker(workerURL);

Полный пример

Я хотел создать экспериментальный пример кода, чтобы показать, как инкапсулировать предыдущую встроенную реализацию Web Workers в объекте JavaScript и использовать его, вот так:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Inline WebWorker</title>
    <meta charset="utf-8" />
    <script>
        // create a namespace for the object
        var workerHelpers = workerHelpers || {};
        
        // set the blob builder and window.URL according to the browser prefix if needed
        var BlobBuilder = BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
        window.URL = window.URL || window.webkitURL;
 
        workerHelpers.InlineWorkerCreator = function () {
        };
 
        workerHelpers.InlineWorkerCreator.prototype = function () {
            createInlineWorker = function (workerBody, onmessage) {
                if (BlobBuilder) {
                    var bb = new BlobBuilder();
                    bb.append(workerBody);
 
                    var workerURL = window.URL.createObjectURL(bb.getBlob());
                    var worker = new Worker(workerURL);
                    worker.onmessage = onmessage;
                    return workerURL;
                }
                else {
                   console.log('BlobBuilder is not supported in the browser');
                    return;
               }
            },
            releaseInlineWorker = function (workerURL) {
                window.URL.revokeObjectURL(workerURL);
            };
 
            return {
                createInlineWorker: createInlineWorker,
                releaseInlineWorker: releaseInlineWorker
            };
        } ();
 
        window.addEventListener('DOMContentLoaded', function () {
            var creator = new workerHelpers.InlineWorkerCreator();
            var workerURL = creator.createInlineWorker('postMessage(\'worker sent message\');', function (e) {
                console.log("Received: " + e.data);
            });
            console.log(workerURL);
 
            // release the URL after a second
            setTimeout(function () { creator.releaseInlineWorker(workerURL); }, 1000);
        }, false);        
    </script>
</head>
<body>
</body>
</html>

Резюме

В посте я объяснил причину создания встроенных веб-работников. Я также показал, как создать встроенный Web Worker, и представил реализацию объекта JavaScript, который можно использовать для этого. 

Буду благодарен за любые комментарии по поводу предоставленного кода.