0

I am facing a problem with setInterval being used in a loop. I have a function subscribeFeed( ) which takes an array of urls as input. It loops through the url array and subscribes each url to getFeedAutomatically() using a setInterval function.

so if three URL's are there in the array, then 3 setInterval's will be called. The problem is 1)how to distinguish which setInterval is called for which URL. 2)it is causing Runtime exception in setInterval( i guess because of closure problem in javascript)

//constructor
function myfeed(){
    this.feedArray = [];
}

myfeed.prototype.constructor= myfeed;
myfeed.prototype.subscribeFeed =function(feedUrl){
      var i=0;
      var url;
      var count = 0;
      var _this = this;
  var feedInfo = {
                url : [],
        status : ""
    };
      var urlinfo = [];
      feedUrl = (feedUrl instanceof Array) ? feedUrl : [feedUrl];
     //notifyInterval = (notifyInterval instanceof Array) ? notifyInterval: [notifyInterval];

    for (i = 0; i < feedUrl.length; i++) {

        urlinfo[i] = {
                url:'',
                notifyInterval:5000,// Default Notify/Refresh interval for the feed 
                isenable:true,      // true allows the feed to be fetched from the URL
                timerID: null,      //default ID is null
                called : false,
                position : 0,
                getFeedAutomatically : function(url){
                    _this.getFeedUpdate(url);
                },
            };


            urlinfo[i].url  = feedUrl[i].URL;

            //overide the default notify interval 
            if(feedUrl[i].NotifyInterval /*&& (feedUrl[i] !=undefined)*/){
                urlinfo[i].notifyInterval = feedUrl[i].NotifyInterval;  
            }


        // Trigger the Feed registered event with the info about URL and status 
        feedInfo.url[i] = feedUrl[i].URL;  

        //Set the interval to get the feed.
        urlinfo[i].timerID = setInterval(function(){
                             urlinfo[i].getFeedAutomatically(urlinfo[i].url);
                        }, urlinfo[i].notifyInterval);

         this.feedArray.push(urlinfo[i]);

        }
    }
// The getFeedUpate function will make an Ajax request and coninue
  myfeed.prototype.getFeedUpdate = function( ){


  }

I am posting the same on jsfiddle http://jsfiddle.net/visibleinvisibly/S37Rj/

Thanking you in advance

2 Answers2

0

After some prototyping i found a answer ,which has the answer,move the closure outside

function myclass(){

}
myclass.prototype.funone= function(){
    var counter =0;
    var timerID;
    timerID = setInterval( function(){
        alert(counter++);
    },1000);

}

myclass.prototype.funtwo= function(){
 var timerID2;
    var counter2 =50;
    timerID2 = setInterval( function(){
        alert(counter2++);
    },2000);    
}

myclass.prototype.funthree = function( ){

    var urlArray =["google.com","yahoo.com"];
    var timeArray =[15000,6000];
    var timerID ;
  for(var i=0;i<2; i++){   
      var url = urlArray[i];
      var timerinterval = timeArray[i];
    timerID =  this.register( url,timerinterval); 
  }       
}
myclass.prototype.register = function(url,timerInterval){

    var myUrl =url;
    var myTimer = timerInterval;
    var timerID  = setInterval( function(){
        alert(myUrl+"with"+ myTimer);
    },myTimer);      

}

var m = new myclass( );
m.funthree( ); 


http://jsfiddle.net/visibleinvisibly/Q4SBG/13/

The move the index binding from the setInterval and pass the url and time interval.
It works perfectly
0

You might want to have a look at this answer (under "The this variable" at the bottom) about what the this value means.

The error in your code may have something to do with using a counter in a loop and creating closures depending on the counter. The simplest way to create such closures is.

for(i=0;i<len;i++){
  object.myCallback = (function(counter){
    return function(){
      doSomethingWith(counter);
    }
  }(i));
}

When creating closures on the fly like that you should be careful not dragging large or large amounts of variables into the closure scope. The link above and code below shows how to do this safely.

I've changed some of the code to make it simpler and not copy stuff that doesn't need to be copied, the setInterval is setTimeout so it only does it once but it's the same idea.

//constructor
function MyFeed(){
  this.feedArray = [];
}
MyFeed.prototype.subscribeFeed =function(feedUrl){
  var i=0,urlInfo=[];
  feedUrl = (feedUrl instanceof Array) ? feedUrl : [feedUrl];
  for (i = 0; i < feedUrl.length; i++) {
    feedUrl[i].isEnable=true;
    feedUrl[i].called=false;
    feedUrl[i].position=0;//not sure what this is supposed to do
    //Set the interval to get the feed.
    feedUrl[i].timerID = setTimeout(this.closures//changed this to timeout
      .getFeedUpdate(this)
      ,feedUrl[i].notifyInterval||100//changed default value
    );
    this.feedArray.push(feedUrl[i]);
    }
};
// The getFeedUpate function will make an Ajax request and coninue
MyFeed.prototype.getFeedUpdate = function( index ){
  console.log("in getFeedUpdate, this is now:",this);
  console.log("my feed url object:",this.feedArray[index].url);
};
//limit closure scope, define closure creators here
MyFeed.prototype.closures={
  //this.closures.getFeedUpdate(this)
  //  will return a closure that calls this.getFeedUpdate
  //  with correct parameters
  getFeedUpdate:function(me){
    var index = me.feedArray.length;
    return function(){
      me.getFeedUpdate(index);
    };
  }
};

//code to test adding single feed
var mf = new MyFeed();
mf.subscribeFeed({
  url:"I am last",
  notifyInterval:1000
});
//add another single feed
mf.subscribeFeed({
  url:"first.com"
});
//and another
mf.subscribeFeed({
  url:"second.com"
});
//and add some more feeds in an array of feeds
mf.subscribeFeed([
  {
    url:"third"
  },
  {
    url:"fifth"
  },
  {
    url:"no, I am last",
    notifyInterval:1500
  }
]);

Try FireFox with the FireBug plugin or Chrome and press F12 to see the console, when the log statements log something you can click on it to see the details of the logged item. Very helpful to log objects like this or simple values like index

Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160