-1

I have looked over this post: setTimeout in Node.js loop in hopes that it would solve my issue, and in a way it has. However, I am encountering a new issue that I am unable to resolve on my own.

I have been trying to fix this issue for the past couple of hours, but I have had no luck. Here is what I have:

The function that needs to be called in the timeout function:

function searchLDAP(i, app, userUID){
    app.process_args(userUID[i]);
}

This is the portion of the code that is not working properly. The code works for the first iteration (userUID[0]), however when it tries to recurse, i becomes undefined.

function doSetTimeout(i, count, app, userUID) {
    if(i == count - 1){ callback(); }    
    searchLDAP(i, app, userUID);

    ++i;
    setTimeout(doSetTimeout, 2000);
}

I am using node's async module

async.series([
    function(callback) {
        app.readLines(input, callback); // userUID is and array that 
                                        // is returned from this function
    },
    function() {
        var count = userUID.length;
        var i = 0;
        doSetTimeout(i, count, app, userUID);
    }
    ], function(err) {
        console.log('all functions complete');
});

Thank you in advance

-Patrick

Community
  • 1
  • 1
Hard Tacos
  • 370
  • 1
  • 5
  • 19

2 Answers2

1

With setTimeout, you only command which function should be called, but do not pass the set of arguments that the function should use. And here's one possible approach to solve this problem:

function doSetTimeout(i, count, app, userUID) {
    if (i == count - 1) { 
      return; // you should stop the recursion
    }

    searchLDAP(i, app, userUID);

    setTimeout(function() {
      doSetTimeout(i + 1, count, app, userUID);
    }, 2000);
}
raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • When I do this, it only returns information for the last element in the array. For example, if I have 5 `userUID`s that need to be passed, it will call `searchLDAP()`5 times, however it will only use `userUID[4]`, not `userUID[0]` then `userUID[1]` ... etc – Hard Tacos Dec 09 '14 at 20:38
  • How exactly does the app `return` information? Wasn't your question about solving the problem with `setTimeout`? – raina77ow Dec 09 '14 at 20:48
  • lol, I misread your answer. It worked. Thank you for your help. I was forgetting to put in `function(){...}` before calling `doSetTimeout` – Hard Tacos Dec 09 '14 at 20:52
  • No problem, that's ok. Indeed, it's too easy both to forget how to end the recursion, and how to start it. ) – raina77ow Dec 09 '14 at 20:54
0

As an alternative to raina77ow's answer, you can also better use async (and dramatically reduce complexity and lines of code) like this:

app.readLines(input, function(err, users) {
    async.each(users, function(user, next) {
        app.process_args(user);
        next();
    }, function(err) {
        console.log('all functions complete');
    });
});

This will iterate over each of your users (the userUID array from you post), and pass the value to the function. No need to mess with tracking the value of i yourself. This isn't rate limited and doens't have the setTimeout which is only necessary if your process_args method cannot handle concurrent calls. If you need make sure that there is only one app.process_args being called at a time, you can use eachSeries instead:

app.readLines(input, function(err, users) {
    async.eachSeries(users, function(user, next) {
        app.process_args(user);
        next();
    }, function(err) {
        console.log('all functions complete');
    });
});

And if for some reason you really need a two second delay between calls, you can do the following:

app.readLines(input, function(err, users) {
    async.eachSeries(users, function(user, next) {
        setTimeout(function() {
            app.process_args(user);
            next();
        }, 2000);
    }, function(err) {
        console.log('all functions complete');
    });
});
Timothy Strimple
  • 22,920
  • 6
  • 69
  • 76