0

I am attempting to execute a chunk of code that is resource intensive to the point it locks the browser while executing. As a workaround, I am trying to use mbostock's queue.js library in conjunction with setTimeout to rate-limit the execution such that the lockup is not noticed by the user. The calls must be made in a specific order but need to have a breathing period in between (currently I'm using 25ms).

I am having trouble figuring out how to link things together.

Specifically, there seems to be an issue with the availability of the 'param' variable inside the setTimeout function scope. When this code executes, param ends up being the same instance for every iteration, not a different instance, as expected.

var q = queue(1);            
var waitParamInits = [];
var keys = Object.keys(attr.customParams);

for (var i=0; i < keys.length; i++) {
    var param = attr.customParams[keys[i]];
    var wait = function(callback) {
        setTimeout(function() {
            if (!param.initializeParm()) {
                handleError('Error initializing parameter: ' + param, false);
            }
        }, 25, param);
    };
    waitParamInits.push(wait);
}

waitParamInits.forEach(function(t) {q.defer(t); });
q.awaitAll(function(error, results) {
    console.log('finished with wait params');
});
mlehmeher
  • 197
  • 2
  • 9

1 Answers1

0

The key here was to use bind(), which cleaned up the code quite a bit in the process. Also, a very important point, is to know that in order for awaitAll() to work correctly, the callback() function that gets passed in by default by the queue.js library MUST be called in order for awaitAll() to know when things are complete.

var q = queue(1);            
var waitParamInits = [];
var keys = Object.keys(attr.customParams);

for (var i=0; i < keys.length; i++) {
    var param = attr.customParams[keys[i]];
    var wait = function(x, callback) { // add the 'x' var to params - 'callback' must be last!
        return setTimeout(function() { // return the setTimeout function
            // bind(), used below in push(), gives us access to 'x' in this scope
            if (!param[x].initializeParm()) {
                handleError('Error initializing parameter: ' + param, false);
            callback(null, 'done with ' + x); // queue.js REQUIRES that the callback it passes in must execute
            }
        }, 25); // remove the 'param' arg
    };
    waitParamInits.push(wait.bind(this, x)); // use bind() to introduce the correct parameter per iteration of the for loop
}

waitParamInits.forEach(function(t) {q.defer(t); });
q.awaitAll(function(error, results) {
    console.log('finished with wait params');
});
mlehmeher
  • 197
  • 2
  • 9