web-dev-qa-db-fra.com

Utilisation d'objets transférables à partir d'un Web Worker

J'ai actuellement ce code pour créer un Web Worker:

w = new Worker("webwork.js");
w.onmessage = function(event) { alert(event.data); }

Et puis le webwork.js code pour le Web Worker:

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);
}

Maintenant, je veux transférer un 128 Mo ArrayBuffer avec ce code:

var r = new ArrayBuffer(1048576*128);
w.postMessage(0, [r]);

Maintenant que j'ai censément transféré la variable r, comment y accéder à partir du Web Worker lui-même. J'ai essayé event.r, juste r, self.r et d'autres choses comme essayer d'ajouter un deuxième argument de fonction pour le tableau de ArrayBuffers, mais rien ne fonctionne.

Comment puis-je accéder aux variables transférées à partir du Web Worker?

29
alt.126
PostMesage(aMessage, transferList)

Dans transferList, vous devez spécifier les objets transférables, contenus dans aMessage:

var objData =
{
    str: "string",
    ab: new ArrayBuffer(100),
    i8: new Int8Array(200)
};
objWorker.postMessage(objData, [objData.ab, objData.i8.buffer]);

De l'autre côté:

self.onmessage = function(objEvent)
{
    var strText = objEvent.data.str;
    var objTypedArray = objEvent.data.ab;
    var objTypedArrayView = objEvent.data.i8;
}
37
CoolCmd

La réponse donnée par sbr fonctionne, mais elle entraînerait une copie des données avant leur envoi au travailleur. Cela pourrait être lent pour une grande quantité de données.
Pour utiliser des "objets transférables", vous transférez en fait la propriété de l'objet vers ou depuis le Web Worker. C'est comme passer par référence là où aucune copie n'est faite. La différence entre celle-ci et la référence de passage normale est que la partie qui a transféré les données ne peut plus y accéder.

Je pense que la façon dont vous devez envoyer les données dans votre exemple est la suivante:

w.postMessage(r,[r]);  // first arg is r, not 0 as in the question

Et la façon dont vous y accéderiez dans le travailleur Web:

addEventListener('message', function(event) {
    var r = event.data;
});

Dans ma propre application, j'avais besoin d'envoyer un grand Float64Array dactylographié du travailleur Web au thread principal, sans la pénalité de performance de la copie. Cela a pris beaucoup d'essais et d'erreurs et de recherches, alors j'ai pensé que je devrais inclure cet exemple ici pour toute autre personne qui se retrouve avec un problème similaire.
Voici le code qui a fonctionné du côté des travailleurs (arr est mon Float64Array):

self.postMessage(arr.buffer, [arr.buffer]);

Sur le fil principal de réception, j'ai:

theWorker.addEventListener('message', function(ev) {
    var arr = new Float64Array(ev.data);  // just cast it to the desired type - no copy made
    // ...
});

Notez que cela fonctionne dans Chrome, mais peut-être pas la plupart des autres navigateurs à ce jour (je n'ai pas encore essayé.)

De plus, si vous souhaitez envoyer d'autres informations en plus du grand tableau, vous pouvez le faire:

self.postMessage({foo:"foo", bar:arr.buffer}, [arr.buffer]);

Sur le thread de réception (dans cet exemple, le principal):

theWorker.addEventListener('message', function(event) {
    var foo = event.data.foo;
    var arr = new Float64Array(event.data.bar);  // cast it to the desired type
    // ...
});
48
yanni

si vous souhaitez utiliser facilement Web Worker, vous pouvez essayer cette petite lib: WW

j'espère que ça aide

0
Erol

Essayez w.postMessage ([0, r]). Pour utiliser des objets transférables, il faut passer le tampon de tableau comme deuxième élément d'un tableau. Voir ceci

0
Wyatt