Использование переносимых объектов из 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. 
}
Другие вопросы по тегам