0

I'm currently having an issue where I have a javascript object that is trying to use setInterval to call a private function inside of itself. However, it can't find the object when I try to call it. I have a feeling that it's because window.setInterval is trying to call into the object from outside but doesn't have a reference to the object. FWIW - I can't get it to work with the function being public either.

The basic requirement is that I may need to have multiple instances of this object to track multiple uploads that are occurring at once. If you have a better design than the current one or can get the current one working then I'm all ears.

The following code is meant to continuously ping a web service to get the status of my file upload:

var FileUploader = function(uploadKey) {
    var intervalId;

    var UpdateProgress = function() {
        $.get('someWebService', {},
        function(json) {
            alert('success');
        });
    };

    return {
        BeginTrackProgress: function() {
            intervalId = window.setInterval('UpdateProgress()', 1500);
        },

        EndTrackProgress: function() {
            clearInterval(intervalId);
        }
    };
};

This is how it is being called:

var fileUploader = new FileUploader('myFileKey');
fileUploader.BeginTrackProgress();
Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
Keith Rousseau
  • 4,435
  • 1
  • 22
  • 28

3 Answers3

8

Use this

 intervalId = window.setInterval(UpdateProgress, 1500);

setInterval with a literal argument will eval this in the global scope where UpdateProgress is not accessible.

Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
  • I didn't know if setInterval allowed passing args like that because all of the examples passed strings. Good to know... – Keith Rousseau May 19 '10 at 12:21
  • It still doesn't seem to be working for me. It no longer throws an error but it never calls that function either... – Keith Rousseau May 19 '10 at 12:28
  • @Keith Rousseau: I don't suppose there's some parts of the code simplified for the purposes of the question? – Andy E May 19 '10 at 12:35
  • @Andy: This certainly is just a fragment of the code, but that part isn't simplified at all. If I call setInterval within an anonymous function then it seems to work. It doesn't like the direct function reference though. – Keith Rousseau May 19 '10 at 12:42
  • Sounds like UpdateProgress hasn't been defined when the setInterval is run, but is set when the first invocation of the anonymous function is. – Sean Kinsey May 19 '10 at 12:45
  • In the interest of not trusting examples, is it a good practise in this case to have `UpdateProgress` as an **object CamelCase** rather than a **var camelCase**? Since `UpdateProgress` is not really an object definition? I'm asking: should `UpdateProgress` be instead represented as `updateProgress`? – Matt Kocaj Nov 29 '11 at 01:43
  • @cottsak If you feel using camelCase will help you not call a method as a constructor, then go ahead :) – Sean Kinsey Nov 29 '11 at 22:22
  • @Sean Ok, so the convention isn't so mainstream then? It's "whatever works for you"? – Matt Kocaj Nov 30 '11 at 01:05
  • 1
    @Cottsak, no it is definitely a convention, but don't feel forced to do so even if everyone else is (unless you want to share it:) – Sean Kinsey Nov 30 '11 at 22:14
2

Because it is an eval expression, it does not have access to the scope that setInterval is created in. Try:

intervalId = window.setInterval(UpdateProgress, 1500)

It is generally good practice to avoid eval style expressions wherever possible. For instance, if you wanted to call several functions from the same timer, you would use an anonymous function instead of a string.

window.setInterval(function () {
    function1();
    function2();
}, 1500)

See also

Community
  • 1
  • 1
Andy E
  • 338,112
  • 86
  • 474
  • 445
0

+1 to Andy E's head (I can't upvote yet, doh!)

Another gotcha that could get you is if you use this from within the called function.

Then doing exactly what Andy has with this addition should get you by.

var that = this;
window.setInterval(function() {
    function1.apply(that);
    function2.apply(that);
}, 1500);
Justin
  • 4,434
  • 4
  • 28
  • 37