Question

I have a very expensive task running on a Worker, similar as this

for(var i = 0; i < 1000000000; i++)
    //operations using i...

How can I make is so that, in that loop, I can check if a message was received from the Worker owner asking it to stop? I would like to have something like this

for(var i = 0; i < 1000000000; i++)
    if(windowDidNotAskToStop())
        //operations using i...

Right now I have a onmessage function registered so I can start listen to message coming from the owner, but it is blocked while my loop is running (obviously).

I imagine that the postMessage calls from the owner are queued somewhere, so I would simply have to access that in order to process the calls from inside my loop.

Was it helpful?

Solution

You’ll have to handle the events as usual and set a flag, but make sure to leave time for the event to be received in your loop, probably using setTimeout:

var exitLoop = false;

(function loop(i) {
    if (exitLoop || i >= 1000000000) {
        return;
    }

    // …

    setTimeout(function () {
        loop(i + 1);
    }, 0);
})(0);

onmessage = function (e) {
    if (e.data === 'stop') {
        exitLoop = true;
    }
};

Or, as a general utility function:

function asyncIterateRange(start, end, callback) {
    var exitLoop = false;
    var doneCallbacks = [];

    (function loop(i) {
        if (exitLoop) {
            return;
        }

        if (i >= end) {
            doneCallbacks.forEach(function (callback) {
                callback();
            });

            return;
        }

        callback(function () {
            setTimeout(function () {
                loop(i + 1);
            }, 0);
        });
    })(start);

    return {
        abort: function abort() {
            exitLoop = true;
        },
        done: function addDoneCallback(callback) {
            doneCallbacks.push(callback);
        }
    };
}

Use it like so:

var innerIterator;
var outerIterator = asyncIterateRange(0, 1000000, function outerLoop(next) {
    innerIterator = asyncIterateRange(0, 1000, function innerLoop(next) {
        // …
        next();
    }).done(next);
});

// To stop:
if (innerIterator) {
    innerIterator.abort();
}

outerIterator.abort();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top