Передавайте большие объемы данных между веб-работником и основным потоком
Есть ли способ передать большие объемы данных (несколько МБ) между веб-работником и основным потоком? Я работаю в проекте, где мне нужно загружать файлы, немного модифицировать их, а затем каким-то образом позволить пользователю загружать измененный файл. Я нашел следующие способы передачи данных между веб-рабочим и основным пользовательским интерфейсом
- Использование обычного метода
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. Я не знаю, является ли это основной причиной, но я надеюсь, что нет, и на самом деле эта функция реализована в других браузерах... возможность обрабатывать выбранные пользователем файлы в фоновом режиме - это хорошая вещь.