Search code examples
typescriptnativescriptweb-workernativescript-vue

How to correctly manage workers in nativescript?


I am currently working on a project involving nativescript-vue and typescript and I must work with workers (im not much familiar with NS and workers). I've read the doc and tried the implementation given in the NS documentation and adapted it to the project but I can't seem to get it right... Indeed it works at first but after calling a few times the method that instantiate and manage the worker, the app crashes without an error... I don't know if its due to the fact that the worker doesn't really close after finishing its task or if there is an issue with the script itself...

this is a part of the code of the main.ts

import "tns-core-modules/globals"

export class Main extends Vue {
   worker: Worker

 onTaskReceived(task){
   this.manageWorker(task, this.worker)
 }

 manageWorker(task: any, worker: Worker){
   const NewWorker = require('nativescript-worker-loader!./worker.ts')
   worker = new Worker()
   worker.postMessage({
                type: "task",
                value: task
   })
   worker.onerror = await function (err) {
                console.log(`An unhandled error occurred in worker: ${err.filename}, line: ${err.lineno} :`);
                console.log(err.message);
                worker.terminate()
   }
   worker.onmessage = function (message) {
                console.log('{onmessage}')
                worker.terminate()
   }
 }
}

and this is the code of one of the worker (worker.ts)

import "tns-core-modules/globals"
import { error } from "tns-core-modules/trace";

const context: Worker = self as any;

context.onmessage = function(task) {
    const request = task.data
    console.log('[WORKER]: data from main received')
    console.log(request)
    # Here is the code that the worker execute when triggered
    if (result.state === 'done') {
        console.log('[WORKER]: work done - sending data back')
        context.postMessage({
            type: 'result',
            succeed: true,
            value: result
        })
    }

}

context.onerror = function (error) {
    console.log('[WORKER]{ERROR} '+error)
}

export default {} as typeof Worker & (new () => Worker)

thank you in advance for your help :)


Solution

  • I see a few errors in your source.

    1. You're importing NewWorker, but then instantiating Worker.
    2. You're importing with a .ts extension.
    3. You call postMessage before assigning onmessage.
    4. You're terminating your worker after one single message is received. It will take longer to boot the worker than to just execute the function in your existing JavaScript context.
    5. Your worker export is different from mine (maybe it isn't an issue?).

    In worker.ts:

    import 'globals';
    
    const context: Worker = self as any;
    
    context.onmessage = (msg: MessageEvent): any => {
        (global as any).postMessage({output: `rx: ${msg.message}`});
    };
    

    In wherever else:

    import * as MyWorker from 'nativescript-worker-loader!./worker';
    
    const worker: MyWorker = new MyWorker();
    worker.onmessage((m: MessageEvent) => { console.log(`(out) ${m.output}`) });
    worker.postMessage({ message: 'Hello, world!' });
    
    // later: worker.terminate();