Использование переносимых объектов из веб-рабочего
В настоящее время у меня есть этот код для создания веб-рабочего:
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
, но ничего не работает.
Как я могу получить доступ к переданной переменной (-ами) от веб-рабочего?
Ответы
Ответ 1
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;
}
Ответ 2
Ответ, заданный 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
// ...
});
Ответ 3
Попробуйте w.postMessage([0, r]). Чтобы использовать переносимые объекты, нужно передать буфер массива в качестве второго элемента массива. См. this
Ответ 4
если вы хотите легко пользоваться веб-рабочим, вы можете попробовать эту небольшую библиотеку:
WW
надеюсь, что это поможет
Ответ 5
это работает для меня:
//в главном
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.
}