2015-08-11 7 views
5

Поскольку Web-Worker JSON сериализации данных между потоками, что-то вроде этого не работает:Как передать пользовательские экземпляры классов через 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!') 

Результат был бы простой объект с потерей прототипа foobar.

Можно ли перенести пользовательский объект обратно в основную нить, не теряя при этом своих прототипов? Например, возможно ли это с ArrayBuffer? Я не знаком с этим, поэтому я немного потерян.

ответ

1
  1. Предполагая, что вы программируете как клиента, так и веб-сервиса можно определить функцию животных в Boths сторон
  2. Затем вы можете добавить к Animal.prototype (с обеих сторон) toJson способ передать информацию, вам нужно обновить объект (и может быть выбрать некоторый атрибут для определения Classname)
  3. вы определяете живительную, которые используют обратный процесс
  4. Затем, когда вы размещаете вы должны всегда JSON.stringify (е)
  5. в OnMessage вы 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

Спасибо за ваш комментарий Эмилио. Хотя ваш скрипт не работает на 100%, я понимаю. Но не будет ли просто «новое животное» (JSON.parse (e.data)) делать то же самое? Нет необходимости в возрождении? Или ваше решение несколько быстрее? Моя основная цель - сохранить большую часть работы внутри рабочего, не блокируя основной поток. –

+0

Да, не работает на 100% (я написал «на лету»). –

+0

Если вы знаете, что вы всегда переносите Животное, вам не нужно все это stuf, вы можете просто передать тогда минимальные данные для его воссоздания. Но если вы можете передать что-либо любого типа, вы можете использовать этот подход. I.e .: 'var zoo = новый зоопарк ({jail1: новый Lion ('pepe', 12), jail2: новый Tigger ('winny', 5)}); worker.postMessage (зоопарк); ' –