Search code examples
javascriptjquerystateweb-workerterminate

When I call terminate on my web worker what state is it in?


I have a web worker that I'm using to poll for information.

Here is the code for starting and stopping the web worker:

var eftWorker = undefined;

that.StartWorker = function () {
    if (eftWorker === undefined) {
        eftWorker = new Worker('../scripts/ETEL.EftWorker.js');
        eftWorker.addEventListener('message', function(e) {
            EftWorkerResponseHandler(e.data);
        }, false);
        eftWorker.addEventListener('error', function(e) {
            EftWorkerErrorResponseHandler(e);
        }, false);
    }

    eftWorker.postMessage({ cmd: eftCmdStart });
};

that.StopWorker = function () {
    if (eftWorker !== undefined) {
        eftWorker.postMessage({ cmd: eftCmdStop });
        eftWorker.terminate();
    }
    eftWorker = undefined;
};

When I call terminate on the worker, because the worker is polling there seems to be a backlog of unprocessed postmessage events.

I'm setting the web worker to "undefined" on initialisation of the containing view and on termination of the web worker. I believe because of the latter, those unprocessed events are shown as ABORT_ERRORs. Is there an intermediate state that I can use to test the existence of the web worker so that I can allow it to process the outstanding events and therefore avoid the errors?

Or is there a different approach that I might use to avoid the accumulation of errors after terminate is called?


Solution

  • Here is my solution to the problem.

    I'm recording the state of the worker in a separate variable in order that I can keep it alive to handle the outstanding messages that are causing the errors.

    Also I'm trapping and discarding any errors generated inside the worker itself.

    var eftWorker = undefined;
    var eftWorkerState = undefined;
    
    var workerStateStarted = 'started';
    var workerStateStopped = 'stopped';
    
    var StartWorker = function () {
        if (eftWorker === undefined | eftWorkerState !== workerStateStarted) {
            eftWorker = new Worker('/scripts/ETEL.EftWorker.js');
            eftWorker.addEventListener('message', function(e) {
                EftWorkerResponseHandler(e.data);
            }, false);
            eftWorker.addEventListener('error', function (e) {
                EftWorkerErrorResponseHandler(e);
            }, false);
        }
    
        eftWorker.postMessage({ cmd: eftCmdStart });
        eftWorkerState = workerStateStarted;
    };
    
    that.StopWorker = function () {
        if (eftWorker !== undefined) {
            eftWorker.postMessage({ cmd: eftCmdStop });
            eftWorker.terminate();
        }
        eftWorkerState = workerStateStopped;
        //eftWorker = undefined;
    };
    
    var EftWorkerResponseHandler = function (msg) {
        try {
            if (eftWorkerState === workerStateStarted) {
                if (msg != '' && msg !== undefined) {
                    var parser = new DOMParser();
                    var xmlDoc = parser.parseFromString(msg, 'text/xml');
    
                    var json = $.xmlToJSON(xmlDoc);
    
                    AlterPaymentUIAccordingToEftWorkerStatus(json);
                }
            }
        } catch (exception) { }
    };
    

    And here's the code from the worker responsible for sending back the status messages.

    EftSendGetRequest = function(passedUrl) {
    
        if (xmlHttpReq === undefined) {
            xmlHttpReq = new XMLHttpRequest();
        }
    
        try {
            xmlHttpReq.open("GET", passedUrl, false);
            xmlHttpReq.send();
        } catch (e) { }
    
        return xmlHttpReq.responseText;
    };