Chenko47
Chenko47

Reputation: 303

Handle nested Interval in Javascript

Some issue here;

I've got an HTTP GET call, that runs in an interval every 3 seconds. The call's response data is an array of objects, and I want to log them to the console.

How can I avoid collision between intervals?

An example:

    setInterval(function(){
        $http.get('/some/api').then(function(dataArray){
            dataArray.forEach(function(element){
                  setInterval(function(){
                      console.log(element);
                  },1000)
            });
        })
    },5000)

Assume that the arrays from the api are: [1,2,3] at the first time, and [4,5,6] at the second interval, I need to see: 1 2 3 4 5 6

Thanks

Upvotes: 0

Views: 862

Answers (2)

guest271314
guest271314

Reputation: 1

Substitute setTimout() for setInterval(); multiply the index of .forEach() callback function by duration 1000

var dataArray = [1, 2, 3];
dataArray.forEach(function(element, index) {
  setTimeout(function() {
    console.log(element);
  }, 1000 * index)
});

You can alternatively call clearInterval() at each successful response, use Promise.all(), Promise() constructor, substitute .map() for .forEach(), call setInterval at .then() chained to Promise.all() when all setTimeout() calls have completed within Promise() constructor

function delay() {
  return $http.get('/some/api').then(function(dataArray) {
    clearInterval(interval);
    return Promise.all(dataArray.map(function(element, index) {
        return new Promise(function(resolve) {
          setTimeout(function() {
            console.log(element);
            resolve();
          }, 1000);
        });
      }))
      .then(function() {
        interval = setInterval(delay, 5000)
      });
  })
}

interval = setInterval(delay, 5000);

function get() {
  return new Promise(function(resolve) {
    resolve(Array.from(Array(Math.floor(Math.random() * 10)).keys()))
  })
}

function delay() {
  return get().then(function(dataArray) {
    clearInterval(interval);
    console.log("current `dataArray.length`:", dataArray.length);
    return Promise.all(dataArray.map(function(element, index) {
        return new Promise(function(resolve) {
          setTimeout(function() {
            console.log(element);
            resolve()
          }, 1000 * index)
        })
      }))
      .then(function() {
        interval = setInterval(delay, 5000)
      });
  })
}

interval = setInterval(delay, 5000)

Upvotes: 2

Rajshekar Reddy
Rajshekar Reddy

Reputation: 18987

I would want to get away from this nested intervals, other approach what I can think of is to have a array that adds on the data into it from each $http.get('/some/api') call and I will have another function outside of this interval which purely works on the array variable. To be clear let see this sample.

var valuesToLog =[];  // holds the elements 

setInterval(function(){
  $http.get('/some/api').then(function(dataArray){
      valuesToLog.push(dataArray);  //keep adding into the array for logging
  })
},5000)

//new player which runs every second.
setInterval(funcion(){
   if(valuesToLog.length){
     console.log(valuesToLog[0]); //log first item
     valuesToLog.splice(0,1) // and remove the logged item. ie: first item
   }
},1000);

So every second I log the first item in the array and remove it.. Also since the interval is never killed it checks the array every second and if items are present it will log..

Hope this is helpful.

Upvotes: 2

Related Questions