Передавайте большие объемы данных между веб-работником и основным потоком

Есть ли способ передать большие объемы данных (несколько МБ) между веб-работником и основным потоком? Я работаю в проекте, где мне нужно загружать файлы, немного модифицировать их, а затем каким-то образом позволить пользователю загружать измененный файл. Я нашел следующие способы передачи данных между веб-рабочим и основным пользовательским интерфейсом

  • Использование обычного метода postMessage.
  • Использование переносимых объектов (только для Chrome)
  • Создайте ссылку на ссылку на blob и только отправьте URL-адрес (также работает в Chrome, в других)?

Я думаю, что (1) отлично подходит для отправки небольших объектов, но занимает много времени и пространства при работе с файлами размером более нескольких МБ, поскольку он сериализуется и отправляется как JSON. Chrome предлагает способ передачи данных с помощью переносимых объектов, где данные не нужно копировать. К сожалению, это пока только функция Chrome, поскольку в противном случае это послужило бы моей цели.

Последнее, что я нашел, - это создать рабочего URL-адреса для blob с помощью self.webkitURL, а затем передать только ссылку URL-адреса для пользовательского интерфейса. Это хорошо работает, я могу предоставить URL-адрес пользователю, и они могут загрузить файл. Я, к сожалению, не нашел способ сделать это в Firefox, возможно ли это?

Существуют ли какие-либо другие методы, которые можно использовать для передачи данных между рабочими и основным потоком?

Ответы

Ответ 1

Firefox/Opera/Chrome в настоящее время поддерживают вкус веб-работников под названием Transferable Objects, который чрезвычайно быстрый - также чрезвычайно прост в настройке. Здесь мы отправляем ww (веб-работнику) выделенный в браузере массив, который заполняется ww и возвращается обратно в сторону браузера. Это передается по ссылке, а не копия: browser ↔ ww

На стороне браузера:

var huge_array = new Float32Array(SIZE);

// worker.postMessage(huge_array.buffer);                      // old way
   worker.postMessage(huge_array.buffer, [huge_array.buffer]); // new Trans Obj

а затем внутри веб-рабочего:

self.onmessage = function(e) {

      var flt_arr = new Float32Array(e.data);

    //  typically you might want to populate flt_arr here

    //  now send data structure back to browser

    // self.postMessage(flt_arr.buffer);                    // old way
       self.postMessage(flt_arr.buffer, [flt_arr.buffer]); // new Trans Obj way
}

Просто разместив объект данных в квадратных скобках [здесь] это позволяет отключить js для использования режима Transferable Object. Это также работает при отправке туда и обратно объектов javascript, содержащих несколько переменных, а не только типизированных массивов.

Чтобы указать:

Переносимые объекты - это объекты, которые не копируются (например, используя что-то вроде структурированного клонирования). Вместо этого данные передаются из одного контекста в другой. "Версия" из вызывающего контекста больше не доступна после переноса в новый контекст. Например, при передаче ArrayBuffer из основного приложения в Worker исходный ArrayBuffer из основного потока очищается и больше не используется. Это значительно улучшает производительность отправки данных в Рабочий

http://html5-demos.appspot.com/static/workers/transferables/index.html https://html.spec.whatwg.org/multipage/workers.html

Ответ 2

В соответствии с этим учебником WebWorkers, WebWorkers теперь поддерживает передачу файлов и объектов Blob и в основном любой объект, который можно использовать с структурированный алгоритм клонирования... или, по крайней мере, Chrome делает это, вероятно, потому, что он вносит изменения в API FileSystem. Я не знаю, является ли это основной причиной, но я надеюсь, что нет, и на самом деле эта функция реализована в других браузерах... возможность обрабатывать выбранные пользователем файлы в фоновом режиме - это хорошая вещь.