Transferable custom classes with ES6 web workers

与世无争的帅哥 提交于 2019-12-23 08:45:49

问题


In Javascript ES6, in the browser, I want to transfer custom class objects to a web worker using the "Transferable" interface. Is this possible? I can find documentation about this for ArrayBuffer objects, but not for custom class objects.

This is not a duplicate of How to pass custom class instances through Web-Workers? since my question is specifically about the Transferable interface. I want to pass my custom class instance to the worker without copying it.


回答1:


I already addressed this question a few times, in different ways. I'm sorry, but the answer to your particular version of this inquiry is definitely no.

There are a few reasons for that.

  1. Individual JavaScript objects are typically not allocated on continuous memory chunks (which would make it possible to transfer them in theory at least).
  2. Any code that converts normal object/class to a ArrayBuffer would really just be overhead over the existing structured clone algorithm, that does the job well.

What you can do,

if you really want to which I'm not so sure you should.

Imagine a class like this:

class Vector2 {
    constructor(existing) {
        this._data = new Float64Array(2);
    }

    get x() {
      return this._data[0];
    }
    set x(x) {
      this._data[0] = x;
    }
    get y() {
      return this._data[1];
    }
    set y(y) {
      this._data[1] = y;
    }
}

It's properties are stored in an array buffer and you can transfer it. But it's not much use yet, for it to work well, we need to make sure it can be constructed from received array buffer. That can be done for sure:

class Vector2 {
    constructor(existing) {
        if(existing instanceof ArrayBuffer) {
            this.load(existing);
        }
        else {
            this.init();
        }
    }
    /*
     * Loads from existing buffer
     * @param {ArrayBuffer} existing
    */
    load(existing) {
      this._data = existing;
      this.initProperties();
    }
    init() {
      // 16 bytes, 8 for each Float64
      this._data = new ArrayBuffer(16);
      this.initProperties();
    }
    initProperties() {
      this._coordsView = new Float64Array(this._data, 0, 2);
    }

    get x() {
      return this._coordsView[0];
    }
    set x(x) {
      this._coordsView[0] = x;
    }
    get y() {
      return this._coordsView[1];
    }
    set y(y) {
      this._coordsView[1] = y;
    }
}

Now you can even subclass it, by passing larger array buffer from the subclass, where both parents and child's attributes will fit:

class Vector2Altitude extends Vector2 {
  constructor(existing) {
    super(existing instanceof ArrayBuffer ? existing : new ArrayBuffer(16 + 8));
    this._altitudeView = new Float64Array(this._data, 16, 1);
  }
  get altitude() {
    return this._altitudeView[0];
  }
  set altitude(alt) {
    this._altitudeView[0] = alt;
  }
}

A simple test:

const test = new Vector2();
console.log(test.x, test.y);
const test2 = new Vector2Altitude();
test2.altitude = 1000;
console.log(test2.x, test2.y, test2.altitude, new Uint8Array(test2._data));

To make some real use of it, you need to solve many other problems, and essentially implement your own memory allocation for complex objects.



来源:https://stackoverflow.com/questions/49320947/transferable-custom-classes-with-es6-web-workers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!