2015-08-11 18 views
5

Dal Web Worker JSON serializzare i dati tra le discussioni, qualcosa come questo non funziona:Come passare istanze di classi personalizzate tramite Web-Workers?

worker.js

function Animal() {} 
Animal.prototype.foobar = function() {} 

self.onmessage = function(e) { 
    self.postMessage({animal: new Animal()}) 
} 

main.js

let worker = new Worker('worker.js') 

worker.onmessage = function(e) { 
    console.log(e.data) 
} 

worker.postMessage('go!') 

Il risultato sarebbe un oggetto semplice con la perdita del metodo prototipo foobar.

È possibile trasferire nuovamente l'oggetto personalizzato al thread principale senza perdere i suoi metodi di prototipo? Come, sarebbe possibile con ArrayBuffer? Non ho familiarità con quella roba, quindi sono un po 'perso.

risposta

1
  1. Supponendo che si programma sia il client e il webservice è possibile definire la funzione degli animali nei lati boths
  2. Quindi è possibile aggiungere a Animal.prototype (in entrambi i lati) toJson metodo per passare le informazioni necessarie per ricreare l'oggetto (e può essere sceglie alcuni attributi per definire il className)
  3. si definisce un reviver che utilizzano il processo inverso
  4. Poi, quando si posta si deve sempre JSON.stringify (e)
  5. Nel onMessage voi JSON.parse (m, reviver)

    function Animal(name, age){ 
        var private_name = name; 
        this.public_age = age; 
        this.log = function(){ 
        console.log('Animal', private_name, this.public_age); 
        } 
        this.toJson = function(){ 
        return JSON.stringify({ 
         __type__:'Animal', // name of class 
         __args__:[this.public_age, private_name] // same args that construct 
        }); 
        }   
    } 
    
    Animal.prototype.age = function(){ 
        return this.public_age; 
    } 
    
    var a = new Animal('boby', 6); 
    
    worker.postMessage(JSON.stringify(a)); 
    
    function reviver(o){ 
        if(o.__type__){ 
        var constructor=reviver.register[o.__type__]; 
        if(!constructor) throw Error('__type__ not recognized'); 
        var newObject = {}; 
        return constructor.apply(newObject, o.__args__); 
        } 
        return o; 
    } 
    
    reviver.register={}; // you can register any classes 
    
    reviver.register['Animal'] = Animal; 
    
    worker.onmessage = function(m){ 
        var a = JSON.parse(e, reviver); 
    } 
    
+0

Grazie per il tuo commento Emilio. Mentre il tuo script non è funzionale al 100%, ho capito il punto. Ma un semplice 'new Animal (JSON.parse (e.data)) non farebbe la stessa cosa? Non c'è bisogno di un reviver? O la tua soluzione è un po 'più veloce? Il mio obiettivo principale è quello di mantenere la maggior parte del lavoro all'interno del lavoratore, senza bloccare il thread principale. –

+0

Sì, non è funzionale al 100% (ho scritto "al volo"). –

+0

Se sai che trasferisci sempre un animale non hai bisogno di tutto questo stuf, puoi semplicemente passare poi i dati minimi per ricrearlo. Ma se puoi passare qualsiasi cosa di qualsiasi tipo, puoi usare questo approccio. I.e .: 'var zoo = new Zoo ({jail1: new Lion ('pepe', 12), jail2: new Tigger ('winny', 5)}); worker.postMessage (zoo); ' –