Search code examples
javascriptobjectweb-worker

Using Synaptic library in Web Workers in JavaScript


I'm trying to create my first web worker in javascript. I got a object called predictor it has methods and attributes using prototype as you can see here:

function Predictor(historical, type) {
    this.historical = historical;
    this.type = type;
    this.NN = this.generateNN(this.historical);
}

Predictor.prototype.getMaxTime = function (historical) {
    return historical.length;
};

I'm using the library synapic.js, with this you can create neuronal networks (NN). Sometimes train a NN it is a expensive progress and the web browser is freezing while the script is finishing the train.

I read about the web workers in order to avoid this problem. I tried to postMessage with the object Predictor and execute predictor.train() in the worker, but the browser said that Predictor it is not a Transferable or Clonable object. As I understrand the messages must be converted to JSON and I can not pass my object as I can do in others languages serializing the class.

The second that I tried it is to create the predictor in the web worker and save it in the worker. I used the method importScripts('../../lib/synaptic/synaptic.js') and importScripts('../model/predictor.js') to use the library and the class that I create but the browser says:

Uncaught ReferenceError: synaptic is not defined

Can I send my object Predictor as param in the function postMessage? What is the best way to fix it?


Solution

  • Why passing the Predictor over message isn't gonna work

    The problem is that just passing the Predictor would not be enough even if you managed to do it. Do not forget that the whole library must be present when working with predictor!

    When you pass objects to web worker, only their own properties are sent, not those from the prototype. So for example the Predictor.prototype.getMaxTime wouldn't pass.

    Why you get synaptic is not defined error (Spoiler: not your fault)

    Many of mine questions as well as other were caused by the same developper's mistake: they use window instead of self.

    In web worker, self contains the global scope as well as the worker methods (eg. postMessage). In browser, self == window.

    So to fix your problem, replace window with self in Synaptic sources.

    Search query in their GitHub repo: https://github.com/cazala/synaptic/search?utf8=%E2%9C%93&q=window

    Fixing error without changing synaptics

    I'm not 100% sure about this, but this might do the trick. But it also might confuse the hell out of libraries that are aware of how workers work:

    // Make global variable window that refers to global scope
    self.window = self;
    // Yes you can pass multiple paths at once
    importScripts('../../lib/synaptic/synaptic.js', '../model/predictor.js');
    // Should work. Next time make a test case so I don't have to shoot blindfolded
     ...