Skip to content

Repository files navigation

Worker Runner

Test in ChromeTest in FirefoxTest in IE11npm version

Worker Runner is a tool to assist use Web Worker.

Table of contents

  1. Initialization
  2. Usage example
  3. ResolvedRunner
  4. Runner token
  5. ResolvedRunner as argument
  6. RunnerResolverLocal
  7. ResolvedRunner as method result
  8. Transfer data
  9. Usage with RxJs
  10. Warning

Initialization

Declare your classes with the methods you need.

exportclassLibraryRunner{// An example of your Runner implementation// Variables will not be available to the ResolvedRunner,// but can be used internally by the Runner instancepublicbooks: string[];constructor(books: string[]){// Constructor can take argumentsthis.books=books;}publicaddBook(book: string): void{this.books.push(book);}// The method can return a resultpubliccheckBook(book: string): boolean{returnthis.books.includes(book);}// The method can return result asynchronouslypublicreserveBook(book: string,time: number): Promise<string>{returnnewPromise(resolve=>setTimeout(()=>resolve(book),time));}}

Declare your instance of RunnerResolverClient in a Client (Main) area.

  • Creating a RunnerResolverClient with a Runner list will slightly speed up the first resolving of the ResolvedRunner because the available methods will not be requested from the Host area. But this will also increase the size of the code loaded into the Client area.
  • You must wait until the asynchronous call to the run() method completes.
// Client areaimport{RunnerResolverClient}from'@worker-runner/promise';constresolver=newRunnerResolverClient({connection: newWorker('./worker.js'),});resolver.run();// await asynchronous

And also declare your instance of RunnerResolverHost in a Host (Worker) area.

  • The RunnerResolverHost instance must have a list of Runner classes. This list may differ from the list used in RunnerResolverClient.
  • Call the run() method.
// Host areaimport{RunnerResolverHost}from'@worker-runner/promise';newRunnerResolverHost({runners: [LibraryRunner]}).run();

Usage example

After you initialized RunnerResolverClient(in client area) and RunnerResolverHost(in host area), you can use the RunnerResolverClient instance to resolve instances of the Runner class that will be used in the client area and executed in the host area.

asyncfunctionmain(){constresolver=newRunnerResolverClient({connection: newWorker('./worker.js'),});awaitresolver.run();constlibraryRunner=awaitresolver.resolve(LibraryRunner,['Book №1']);awaitlibraryRunner.addBook('Book №2');constisExist=awaitlibraryRunner.checkBook('Book №2');console.log('Book №2 exist:',isExist);// => Book №2 exist: trueconstreservedBook=awaitlibraryRunner.reserveBook('Book №1',100);console.log('Reserve ended for:',reservedBook);// => Reserve ended for: Book №1awaitlibraryRunner.destroy();}main();

ResolvedRunner

Runner that was resolved by RunnerResolverClient has the same methods as the original Runner instance. All called methods will be executed asynchronously and the result of the calculation will be obtained using Promise.
ResolvedRunner also has a set of methods:

  • destroy()
    Destroying and remove Runner instance from resolved Runners list in RunnerResolverClient and RunnerResolverHost instance.

  • disconnect()
    Unsubscribe from runner, if the control object was the last, then runner will be automatically destroyed.

  • cloneControl()
    Returns a new control object for the same Runner instance.

  • markForTransfer()
    When a Runner is flagged for transfer, if it is used as argument or as method result, the original control will be transferred. The original ResolvedRunner will lose control. In this case, the transfer of the ResolvedRunner will be faster because it will not take time to request a copy of the control. It is convenient to use as an automatic disconnect after returning the result of a method.

Runner token

RunnerResolver takes a list of Runners as a parameter. For each such Runner, you can set your own identifier - a token. To do this, add an object with parameters to the list, for example:

constresolver=newRunnerResolverClient({// ...runners: [{runner: LibraryRunner,token: 'LibraryRunnerToken',},{token: 'LibraryPoolRunnerToken',}],});

You can resolve the ResolvedRunner instance, by token. This will reduce the bundle size and load only the code you need into each area. (This configuration is optional for the RunnerResolverClient. You can use a token without preconfiguration.)
By default, if you have not set a token, then the class name will be used.
WARNING: It is recommended to set a token. Using the class name is not recommended, because after minification, the names of the same class may differ for different bundles (areas).

ResolvedRunner as argument

You can use the resolved instance as constructor or methods arguments. Resolved instance can be declared in another RunnerResolver and area.

exportclassLibraryPoolRunner{// ...constructor(...libraries: ResolvedRunner<LibraryRunner>[]){// ...}addLibrary(library: ResolvedRunner<LibraryRunner>): void{// ...}}// ...constlibraryRunners=awaitPromise.all([resolver1.resolve(LibraryRunner,[]),resolver2.resolve(LibraryRunner,[]),]);constlibraryPoolRunner=awaitresolver3.resolve(LibraryPoolRunner,libraryRunners[0]);awaitlibraryPoolRunner.addLibrary(libraryRunners[1]);

RunnerResolverLocal

The original Runner instance will run in the same area in which it was resolved / wrapped. RunnerResolverLocal can be used to replace RunnerResolverClient to simplify debugging in development mode and for testing.
That allows to use a local Runner as method result or pass it as argument.

// ...constlocalResolver=newRunnerResolverLocal();constresolvedLibraryRunner=awaitlocalResolver.resolve(LibraryRunner,[]);constresolvedLibraryPoolRunner=awaitresolver.resolve(LibraryPoolRunner);resolvedLibraryPoolRunner.addLibrary(resolvedLibraryRunner);resolvedLibraryRunner.disconnect();// ...

WARNING: Remember to call the disconnect() or destroy() method, as appropriate, to avoid memory leaks.

ResolvedRunner as method result

If the method returns the ResolvedRunner as the return value, then its control object will be copied and transferred.

exportclassLibraryPoolRunner{// ...publicresolveLibrary(id: number): ResolvedRunner<LibraryRunner>{returnthis.resolvedLibraryRunners[id];}}

WARNING: If you want the ResolvedRunner to be automatically disconnected after returning the result of the method, in order to avoid memory leak, call the markForTransfer() method, in which case the control will not be copied, but transferred. At the same time, the original ResolvedRunnerwill lose control.

exportclassLibraryPoolRunner{// ...publicresolveLibrary(id: number): ResolvedRunner<LibraryRunner>{returnthis.localResolver.wrapRunner(this.libraryRunners[id]).markForTransfer();}}

Transfer data

If you need to use Transferable data as an argument or as a result of a method, wrap such data in the TransferRunnerData class.

exportclassArrayBufferRunner{// ...publicresolveLibrary(id: number,data: ArrayBuffer,): TransferRunnerData<{id: number,data: ArrayBuffer},ArrayBuffer>{// ...returnnewTransferRunnerData({ id, data},[data]);}}// ...constarrayBuffer=newArrayBuffer(8);// ...resolvedArrayBufferRunner.resolveLibrary(0,newTransferRunnerData(arrayBuffer,[arrayBuffer]),);

Usage with RxJs

You can also use RxJS Observable (or Subject) to receive events from Host area. To do this, use the @worker-runner/rx library.

exportclassLibraryRunner{privatenotification$=newSubject<string>();// ...publicnotification(): Observable<string>{returnthis.notification$;}}// ...constresolver=newRxRunnerResolverClient({runners: [LibraryRunner],connection: newWorker('./worker.js'),});awaitresolver.run();constlibraryRunner=awaitresolver.resolve(LibraryRunner);(awaitlibraryRunner.notification()).subscribe(()=>{// ...})

Warning

  • Internet Explorer requires polyfill for Promise.
  • Unfortunately the generic type cannot handle the interface correctly, but it does work correctly with type alias and class. Therefore, it is recommended to use type alias instead of interface to describe the type of your method arguments.
  • The library is compiled using the ES2015 standard. If you need support for older browsers such as Internet Explorer, then you will need to recompile the library using ES5 and Promise polyfill. You can see an example of configuring webpack here.

About

Worker Runner is a tool to assist use Web Worker.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages