0.0.9 • Published 1 year ago

arbeiter v0.0.9

Weekly downloads
-
License
-
Repository
-
Last release
1 year ago

Arbeiter

A worker-helper for in-browser. Allows for dynamically creating workers with manageable state.

How to use

  • simple example
import Arbeiter from "arbeiter";

// The arbeiters' types have to be explicitly typed inside Arbeiter's generic.
const arbeiter = new Arbeiter<{ 
  counter: number; 
  increment: () => number 
}>();

const { methods, terminate } = arbeiter.construct(() => ({
  counter: 0,
  increment: function () {
    // only state accessed with `this` can be manipulated
    return this.counter++;
  },
}));

// All functions are converted into async functions
// and are accessible in `methods`
methods.increment().then(
  value => value // 1
);
  • transfer OffscreenCanvas
import Factory from "arbeiter";

const arbeiter = new Arbeiter<{
  canvas?: OffscreenCanvas,
  context?:
  transfer: (canvas: OffscreenCanvas) => void
  fill: (color: string) => void
}>();

const { methods, terminate } = arbeiter.construct(() => ({
  canvas: undefined,
  transfer: function (canvas) {
    this.canvas = canvas;
    this.context = this.canvas.getContext('2d');
  },
  fill: function(color) {
    if (!this.context) return;
    this.context.fillStyle = color;
    this.context.fillRect(0, 0, 100, 100);
  }
}));

const canvas = document.createElement('canvas');

// Transferable objects are automagically transferred
methods.transfer(canvas.transferControlToOffscreen()).then(
  () => methods.fill("red")
)
  • function-parameters
import Arbeiter from "arbeiter";

const arbeiter = new Arbeiter<{
  func: (callback: (number: number) => void) => void;
}>();

const { methods, terminate } = arbeiter.construct(() => ({
  func: function (callback) {
    callback(Math.random());
  },
}));

// All functions passed as arguments have to be serializable 
// Variables available on `this` can be accessed and manipulated
methods.func(number => 
  console.log("random number", number)
); // worker will log `random number 0.1522...`
methods.func(number => 
  console.log("number random", number)
); // worker will log `number random 0.1522...`

// Functions can normally not be serialized with workers
// To be able to pass and execute the function
// Arbeiter uses `.toString` and `eval` under the hood 

// `eval` has performance and security implications, so be careful.
  • options-config
// You can disable passing around and `eval`ing functions 
// with an optional secondary parameter
arbeiter.construct(
  () => ({
    func: function (callback) {
      // will give type-error, since callback will be a string
      callback(Math.random());
    },
  }),
  {
    eval: false,
  }
);

// if options.methods[methodName].eval is defined, 
// it will overwrite the global config
arbeiter.construct(
  () => ({
    func: function (callback) {
      // will give type-error, since callback will be a string
      callback(Math.random());
    },
  }),
  {
    eval: true,
    methods: {
      func: {
        eval: false,
      },
    },
  }
);
// If you want to remove the overhead of the arbeiter 
// responding back after each execution
// You can disable this functionality inside 
// the config with the `async`-parameter

// The methods affected will not be cast to a sync function
// but the async functions will never resolve

const { methods } = arbeiter.construct(
  () => ({
    func: function (callback) {
      return "resolved";
    },
  }),
  {
    async: false,
  }
);

methods.func().then(message => 
  console.log(message)
); // console.log() will never be called

// Just as with `eval`, `async` can be configured for individual methods too
const { methods, terminate } = factory.construct(
  () => ({
    func: function (callback) {
      return "resolved";
    },
  }),
  {
    async: false,
    methods: {
      func: {
        async: true,
      },
    },
  }
);

methods.func().then(message => 
  console.log(message)
); // console.log() will be called
  • terminate workers
import Factory from "arbeiter";

const arbeiter = new Arbeiter<{}>();

const { methods, terminate } = arbeiter.construct(() => ({}));

// Individual workers can be terminated with terminate()
terminate()

// To terminate all workers constructed with the arbeiter
arbeiter.terminate()

Acknowledgements

I took the idea of making workers dynamically with .toString from worktank. worktank's focus is pooling, pure functions (in dynamic mode) and isomorphic code. arbeiter does not have any pooling-functionality currently, allows for state to be initialized/managed, and is currently only available in-browser.

0.0.9

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago