0

I am having trouble with Javascript async call. The Car class below has a move function which takes two arguments, the first one is a value, the second one is a call back function, which will be called after 1 second, and this callback function takes the value returned by forward method.

var Car = function() {
  this._count = 0;
};

Car.prototype = {
  move: function(value, onMoved) {
    setTimeout(function() {
      onMoved(this.forward(value));
    }.bind(this), 1000);
  },
  forward: function(value) {
    this._count = this._count + value;
    return this._count;
  }
};

I want to call the move function like this:

var values = [1, 2, 3, 4];
var car = new Car();

values.forEach(function(value) {
  car.move(value, function(result) {
    console.log(result);
  });
});

Now my problem is the call back function onMoved does not wait for 1 second to execute between each value that it is outputting. How can I make it so it wait between each value that it is outputting? I am allowed to use underscore.js. Thanks.

3
  • 3
    "does not wait for 1 second to execute" — Yes, it does. Commented Jul 13, 2015 at 18:09
  • 1
    Are you asking how to make it wait between each value that it is outputting? At the moment it is waiting for one second after you run your (entire) forEach loop. Commented Jul 13, 2015 at 18:10
  • @Quentin, yes, you are right, I modified my question. Commented Jul 13, 2015 at 18:14

2 Answers 2

1

setTimeout in javascript registers callback function in a queue to execute in future once the current execution stack is free. for example:-

while(1){
 setTimeout(function(){
   console.log('hello');
 },1000);
}

this will not print hello as the execution stack will never be free.

Coming back to the example we call move method which will be pushed to a queue. After one second it starts executing each function one by one without any delay as the setTimeout is set to a fixed time ie. 1000 millisecond.

workaround:-

var Car = function() {
  this._count = 0;
};

Car.statCount = 0;

Car.prototype = {
 move: function(value, onMoved) {
  this.constructor.statCount++;
  setTimeout(function() {
    onMoved(this.forward(value));
  }.bind(this), 1000*Car.statCount);
 },
 forward: function(value) {
   this._count = this._count + value;
   return this._count;
 },
 constructor: Car
};


var values = [1, 2, 3, 4];
var car = new Car();

values.forEach(function(value) {
  car.move(value, function(result) {
    console.log(result);
  });
});
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. This works great. Is it possible to stop the timer if result in the callback function contains errors?
if you need more control over it then use a register method to store all and start move once all are registered. Please find the link where i have modified the example link
0

Since you want a 1 sec. wait between each call, you might consider using the setInterval method on window, instead of utilizing the setTimeout method:

You could add some method performing some actions for each iteration, and finish iterating when all values are processed:

var i=0;
function go(result) { 
    if (!!values[i]) {
        car.move(values[i], function(result) {console.log(result);})
        i++;
    } else {
        window.clearInterval(interval);
    }
}

And call this function using setInterval

var interval = window.setInterval(go, 1000);

Have a look at the following fiddle:
https://jsfiddle.net/adw1k98m/1/

(see console log for output)

Comments

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.