1

I bet I have a common problem, but as I am still new to async javascript I am not sure what the (best) solution for my problem is.

I go through a for loop and in that loop i call a method including a callback method. In the callback method I want to know which loop is the latest one. But the method takes a little bit to proceed and at the time when it is completed once, the for loop around it is finished and the counter variable i is already at highest. So my question is, how can I determine the latest loop in the callback method?

Here is example code for it.

var i;
for (i = 0; i < numMessages; i++){
    var lastMessage;
    if (i+1 === numMessages) {
        lastMessage = true;
    }
    else {
        lastMessage = false;
    }
    twilioClient.sendMessage({
        to: recipientNumber,
        from: zenyaTwilioNumber,
        body: (numMessages > 1? (i+1) + '/' + Math.ceil(options.messageBody.length/153) + ': ' + options.messageBody.substring(i*153, (i+1)*153): options.messageBody)
    }, 
    function (err, res) {
        if (err) {
            callback({error: err});
        }
        else {
            console.log('Message:' +i);
            console.log('numMessages: ' + numMessages); // Even after method is executed once, the lastMessage variable is already true
            if (lastMessage) {
                var returnObj = {
                    status : status,
                    recipient : res.to,
                    statusMessage : res.status
                };
                callback({result: returnObj}); // The callback should only be called once here.
            }
        }
    });
}

Looking forward to your answers and learning best practice about how to achieve that.

Thanks, benni

bdifferent
  • 703
  • 4
  • 12
  • 2
    Closure issue: https://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1 You have to capture the variable. About loops: [JavaScript closure inside loops – simple practical example](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Shanoor Dec 22 '15 at 11:46

1 Answers1

0

You need to create a function that:

  • takes the parameters you want to access in the callback
  • returns the callback function

Then you call that function with actual parameter values.

So instead of:

function (err, res) {
    // ...
}

You need:

(function(i, lastMessage) {
    return function(err, res) {
        // ... 
    }
})(i, lastMessage)

Applying it to your example:

var i;
for (i = 0; i < numMessages; i++){
    var lastMessage;
    if (i+1 === numMessages) {
        lastMessage = true;
    }
    else {
        lastMessage = false;
    }
    twilioClient.sendMessage({
        to: recipientNumber,
        from: zenyaTwilioNumber,
        body: (numMessages > 1? (i+1) + '/' + Math.ceil(options.messageBody.length/153) + ': ' + options.messageBody.substring(i*153, (i+1)*153): options.messageBody)
    }, 
    (function(i, lastMessage) {
        return function (err, res) {
            if (err) {
                callback({error: err});
            }
            else {
                console.log('Message:' + i);
                console.log('numMessages: ' + numMessages);
                if (lastMessage) {
                    var returnObj = {
                        status : status,
                        recipient : res.to,
                        statusMessage : res.status
                    };
                    callback({result: returnObj}); // The callback should only be called once here.
                }
            }
        };
    })(i, lastMessage)); 
}
Lukasz Wiktor
  • 19,644
  • 5
  • 69
  • 82