0

I currently have this situation...

function loop (num1, callback) {
    for (i = 0; i < num1; i++) {
        console.log("loop count: " + i);
        callback();
    }
}

Which is currently outputting the following sample results:

loop count: 1
loop count: 2
loop count: 3
...
loop count: num1 - 1
callback output 1
callback output 2
callback output 3
...
callback output num1 - 1

What I would like it to do is wait until each callback has finished executing and outputting its result before moving onto the next item in the loop. i.e. as per the sample output below:

loop count: 1
callback output 1
loop count: 2
callback output 2
loop count: 3
callback output 3
...
loop count: num1 - 1
callback output num1 - 1

Does anyone know how I can achieve this sequential / synchronous mode of operation in my function?

Thanks in advance for the help!

UPDATE...

Ok so the call back function is being called like so...

loop(10, updateDB);

And the callback function passed to loop is as follows...

function updateDB(sql_string, responseObject) {
  var mysql = require('mysql');
  var connection = mysql.createConnection({
      host : 'localhost',
      user : 'user',
      password : 'password',
      database : 'database',
  });
  connection.connect();
  var query = sql_string;
  connection.query(query, function(err, results) {
      connection.end();
      if (err) {
        console.log(err);
        responseObject.push({"queryStatus":"FAIL"});
      }
      if (err == null) {
        console.log('Changed ' + results.changedRows + ' rows');
        responseObject.push({"queryStatus":"PASS"});
      }
  });
};
11
  • Is the callback function asynchronous? Commented Mar 28, 2017 at 0:53
  • Where does callback output i come from? Commented Mar 28, 2017 at 0:56
  • You can't achieve that with a for loop. You cannot pause it to manually call next() as you can in other languages. Besides, depending on the value of num, using callback could end up in an error after reaching the maximum nesting depth Commented Mar 28, 2017 at 0:56
  • 3
    This does work. Your problem is inside callback. Its obviously synchronous. Commented Mar 28, 2017 at 0:59
  • 2
    @Lux - if it were synchronous then wouldn't the output be as "expected"? I think you meant that callback is asynchrnonous Commented Mar 28, 2017 at 1:13

2 Answers 2

4

Your callback is obviously asynchronous, but that doesn't void your desire to force it to execute in its entirety before moving on in your loop. Here's a way by using Promises to call the next loop cycle.

function loop(max, callback, i) {
  i = i || 0;
  if (i < max) {
    console.log("loop count: " + i);
    return callback(i).then(function() {
      return loop(max, callback, ++i);
    });
  }
}

function doAsyncStuff(passedNum) {
  return new Promise(function(resolve, reject) {
    // Fake asynchronous stuff for 500ms using setTimeout.
    // Put your real async code here, calling "resolve" when
    // it's finished.
    setTimeout(function() {
      console.log("callback count: " + passedNum);
      resolve();
    }, 500);
  });
}

loop(5, doAsyncStuff).then(function() {
  console.log('All done looping!')
});

Sign up to request clarification or add additional context in comments.

5 Comments

You might want to put the "real async code" from the question in your answer
@Bergi Huh? The promise is returned, otherwise the snippet wouldn't work. Also, I'd rather have a working code snippet that teaches someone how to implement Promises than a non-working snippet that pastes in a block of code that is not relevant to the OP's original question, which was how to use Promises to make the loop's cycle work with an asynchronous callback.
Neither your loop function nor the then callback function inside it return promises, despite being asynchronous.
@Bergi Sure. It's a little out of scope for the question, but fine idea. Updated and thanks!
@rgthree this is an amazing answer, achieves exactly what I want in a very elegant way. Thank you very much for your help.
0

You can use this using promise of javascript

 function callback(item) {
   return new Promise(function(resolve, reject) {
    console.log('callback item ', item);
    resolve(item);
   });
 }

 function loopCall(num) {
   for (var i = 1; i < num; i++) {
         console.log('loop item ', i);
         callback(i).then(function(data) {

         }, function(err) {
            console.log(err);
            console.log('Something Broke');
         })
   }
 }

loopCall(120);

This is the way you can get your desired output.If you want use node.js environment and there has a npm module async.

I hope it will be helpfull.

2 Comments

Thanks for the answer, this is very helpful. I have accepted the answer above though as it is more comprehensive.
This answer is just wrong. It only works because the console.log('callback item ', item); in callback is synchronously invoked

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.