Использование переносимых объектов из Web Worker
В настоящее время у меня есть этот код для создания веб-работника:
w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }
А потом webwork.js
код для веб-работника:
self.onmessage = function(event) {
//var ss=r; //Causes error because of undefined
var ss="";
for(var currProp in event) {
ss+=("event."+currProp+"="+event[currProp]+"\n");
}
postMessage(ss);
}
Теперь я хочу передать 128-мегабайт ArrayBuffer
с этим кодом:
var r = new ArrayBuffer(1048576*128);
w.postMessage(0, [r]);
Теперь, когда я предположительно передал переменную r
Как я могу получить к нему доступ из самого веб-работника. я пытался event.r
, просто r
, self.r
и другие вещи, такие как попытка добавить второй аргумент функции для массива ArrayBuffers
, но ничего не работает.
Как я могу получить доступ к перенесенной переменной (переменным) из Web Worker?
5 ответов
PostMesage(aMessage, transferList)
В transferList
Вы должны указать переносимые объекты, которые содержатся в aMessage
:
var objData =
{
str: "string",
ab: new ArrayBuffer(100),
i8: new Int8Array(200)
};
objWorker.postMessage(objData, [objData.ab, objData.i8.buffer]);
С другой стороны:
self.onmessage = function(objEvent)
{
var strText = objEvent.data.str;
var objTypedArray = objEvent.data.ab;
var objTypedArrayView = objEvent.data.i8;
}
Ответ, данный sbr, работает, но это приведет к тому, что копия данных будет сделана до того, как она будет отправлена работнику. Это может быть медленным для большого количества данных.
Чтобы использовать "передаваемые объекты", вы фактически передаете право собственности на объект веб-работнику или от него. Это как передача по ссылке, когда копия не сделана. Разница между ним и обычной передачей по ссылке заключается в том, что сторона, которая передала данные, больше не может получить к ней доступ.
Я считаю, что вы должны отправить данные в вашем примере:
w.postMessage(r,[r]); // first arg is r, not 0 as in the question
И способ, которым вы бы получили к нему доступ в веб-работнике:
addEventListener('message', function(event) {
var r = event.data;
});
В моем собственном приложении мне нужно было отправить большой типизированный массив Float64Array от веб-работника в основной поток без потери производительности копии. Потребовалось много проб и ошибок и поиска, поэтому я решил, что мне следует включить этот пример сюда для всех, кто столкнулся с подобной проблемой.
Это код, который работал на рабочей стороне (arr - мой Float64Array):
self.postMessage(arr.buffer, [arr.buffer]);
На принимающей основной ветке у меня есть:
theWorker.addEventListener('message', function(ev) {
var arr = new Float64Array(ev.data); // just cast it to the desired type - no copy made
// ...
});
Обратите внимание, что это работает в Chrome, но, возможно, не в большинстве других браузеров на эту дату (еще не пробовал).
Кроме того, если вы хотите отправить другую информацию в дополнение к большому массиву, вы можете сделать это:
self.postMessage({foo:"foo", bar:arr.buffer}, [arr.buffer]);
На принимающей (в этом примере основной) теме:
theWorker.addEventListener('message', function(event) {
var foo = event.data.foo;
var arr = new Float64Array(event.data.bar); // cast it to the desired type
// ...
});
Если вы хотите легко использовать веб-работника, вы можете попробовать этот небольшой lib: WW
Надеюсь, поможет
Попробуйте w.postMessage([0,r]). Чтобы использовать передаваемые объекты, необходимо передать буфер массива как второй элемент массива. Смотрите это
Это работает для меня:
//в основном
var x = new ArrayBuffer(1048576*128);
w.postMessage({buffer: x});
// В рабочем потоке, в обработчике сообщений,
processMessage: function(ev){
var buffer = ev.data.buffer,
// other stuff . buffer is referenced correctly here.
}