如何通过Web-Workers传递自定义类实例?

Mar*_*der 6 javascript buffer data-transfer web-worker arraybuffer

由于Web-Worker JSON在线程之间序列化数据,所以这样的东西不起作用:

worker.js

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

self.onmessage = function(e) {
  self.postMessage({animal: new Animal()})  
}
Run Code Online (Sandbox Code Playgroud)

main.js

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

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

worker.postMessage('go!')
Run Code Online (Sandbox Code Playgroud)

结果将是foobar原型方法丢失的简单对象.

是否可以将自定义对象传回主线程而不会丢失其原型方法?就像,这可能ArrayBuffer吗?我不熟悉那些东西,所以我有点迷茫.

Emi*_*zer 2

  1. 假设您对客户端和网络服务都进行了编程,您可以在双方都定义 Animal 函数
  2. 然后你可以添加到 Animal.prototype (在两侧)toJson方法来传递重新创建对象所需的信息(并且可以选择一些属性来定义类名)
  3. 您定义一个使用相反过程的恢复程序
  4. 然后,当您发布时,您必须始终 JSON.stringify(e)
  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);
    }
    
    Run Code Online (Sandbox Code Playgroud)