Передача объектов веб-работнику
Я пытаюсь передать объект веб-работнику через функцию postMessage.
Этот объект представляет собой квадрат, который имеет несколько функций, чтобы нарисовать себя на холсте и некоторых других вещах. Веб-работник mus возвращает массив этих объектов.
Проблема в том, что когда я вызываю функцию postMessage с этим объектом, я получаю эту ошибку:
Uncaught Error: DATA_CLONE_ERR: DOM Exception 25
Я получаю это как отправку объекта рабочему, так и наоборот.
Я думаю, что ошибка связана с тем, что javascript должен сериализовать объект, но не может этого сделать, потому что объект имеет встроенные функции.
У кого-нибудь была подобная проблема? Вы знаете какой-то рабочий стол?
Спасибо заранее.
Ответы
Ответ 1
Есть несколько причин, по которым вы можете указать ошибку, которую вы упомянули, причины перечислены здесь.
При отправке объектов веб-рабочим объект сериализуется и затем десериализуется в веб-работнике, если объект является сериализуемым объектом.
Это означает, что методы для объектов, которые вы отправляете своему веб-рабочему, не являются тем, что может быть передано веб-работнику (в результате чего вы столкнулись с ошибкой), и вам нужно будет предоставить необходимые методы/функции к объектам на стороне веб-рабочего окружения и убедитесь, что они не являются частью объекта, который передается веб-работнику.
Ответ 2
Как вы подозревали, что объекты с функциями не могут быть опубликованы. То же самое касается объектов с рекурсивными ссылками, но в некоторых браузерах это изменилось в последнее время. Вместо того, чтобы рисковать делать ручную и дорогостоящую сериализацию для каждого сообщения, вы можете выполнить тест в начале вашего script, чтобы определить, какие функции использовать для отправки/получения данных.
У меня была такая же проблема и она была решена, переместив почти весь код в рабочего и просто удерживая рендерер (обертывающий 2d-средство визуализации контекста) в основном потоке. В рабочем я сериализую различные призывы рисования, предназначенные для холста, только для чисел в массиве (типизированном). Затем этот массив отправляется в основной поток.
Так, например, когда я хочу нарисовать изображение, я вызываю метод drawImage()
на мой рабочий экземпляр рендеринга у рабочего. Вызов преобразуется в нечто вроде [13,1,50,40]
, которое соответствует перечислению метода draw, уникальному идентификатору изображения и его координатам xy. Несколько вызовов буферизуются и помещаются в один и тот же массив. В конце цикла обновления массив отправляется в основной поток. Принимающий основной экземпляр визуализатора анализирует массив и выполняет соответствующие вызовы рисования.
Ответ 3
Недавно я столкнулся с этой проблемой при использовании веб-работников. Все, что я передал моему работнику, сохранил все свои свойства, но загадочно потерял все его методы.
Вам нужно будет определить методы в веб-рабочем script. Одним из способов является определение importScripts
класса и вручную установить свойство __proto__
всего, что вы получаете. В моем случае я хотел передать объект grid
, определенный в grid.js
(yup, я работал над 2048), и сделал это так:
importScripts('grid.js')
onMessage = function(e) {
e.data.grid.__proto__ = Grid.prototype;
...
}
Ответ 4
Реальная проблема с объектом и веб-работниками связана с методами этих объектов. Объект не должен иметь методы только свойств.
Пример:
var myClass = function(){
this.a = 5;
this.myMethod = function(){}
}
var notParseableObject = new myClass();
var myClass2 = function(){
this.a = 5;
}
var parseableObject = new myClass2();
Первая не работает (с указанным сообщением об ошибке) с postMessage, а вторая будет работать.
Ответ 5
взгляните на плагин vkThread
http://www.eslinstructor.net/vkthread/
он может передать функцию рабочему, включая функцию с контекстом (метод объекта). Он также может передавать функции с зависимостями, анонимными функциями и лямбдами.
- Вадим
Ответ 6
Когда вы передаете данные веб-работнику, копия данных производится с помощью структурированного алгоритма клонирования. Он указан в HTML5 (см. § 2.9: Безопасная передача структурированных данных).
MDN имеет обзор поддерживаемых типов. Поскольку функции не поддерживаются, попытка клонирования объектов, содержащих функции, будет поэтому генерировать исключение DATA_CLONE_ERR
.
Что делать, если у вас есть объект с функциями?
-
Если функции не актуальны, попробуйте создать новый объект, содержащий только те данные, которые вы хотите перенести. Пока вы используете только поддерживаемые типы, отправка должна работать. Используя JSON.stringify
и JSON.parse
также может используется как обходной путь, поскольку stringify
игнорирует функции.
-
Если функции важны, нет никакого переносного способа. Существуют попытки использовать комбинацию toString
и eval
(например, используется jsonfs библиотека), но это не будет работать во всех случаях. Для экземпляров он будет разбит, если ваша функция - это собственный код. Также закрыты проблемы.