-2

What I'm trying to do is create a object that will handle my ajax calls, I need to repeatedly refresh a few pages over and over again, and create a object for each page is the only way I can think of to do that, and still have the ajax code asynchronous. But whenever I test this nothing is happening and I don't know why.

Here is my code

function PageLoader(url,id,repeatTime){
    this.id = id;
    this.url = url; 
    this.repeatTime = repeatTime;

    this.start = function(){        
        var time = Date.now();
        var xml = new XMLHttpRequest();

        xml.open("GET",this.url,true);
        xml.onreadystatechange = function(){        
            if(xml.readyState === 4){
                document.getElementById(this.id).innerHTML = xml.responseText+" <small>("+(Date.now()-time)+")</small>";

                if(this.repeatTime > 0){
                    setTimeout(this.start,this.repeatTime);
                }
            }
        }

        xml.send(null);
    }

    this.stop = function(){
        this.repeatTime = -1;
    }
}

And here is how I try to run it.

var infoAjax = new PageLoader('../modules/userinfo.php','StatusInfo',1000);

//Load everything automaticly
window.onload = function(){
    infoAjax.start();
}
Yemto
  • 613
  • 1
  • 7
  • 18
  • 1
    See [How to access the correct `this` / context inside a callback?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback). It would be better if you explained your problem properly, then we can provide better help. If you just want to know how to do OOP in JavaScript, have a look at the MDN documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript – Felix Kling Jun 12 '14 at 21:19
  • 1
    I'm failing to understand exactly what the problem here is. Throw a "new" in front of this and voila - new object. – Stephen Jun 12 '14 at 21:19
  • 2
    "not working" is not useful. what is the exact progblem? (BTW, JavaScript has no classes, it uses prototypal inheritance.) – The Paramagnetic Croissant Jun 12 '14 at 21:19
  • it looks right... what are you trying to use to create the object? – pseudonym117 Jun 12 '14 at 21:19
  • The problem is that the responseText never shows up on the element, and even if I use an alert to new it, the timeout never happens since I only get one alert call. – Yemto Jun 12 '14 at 21:50
  • 1
    Have a look at the question I linked to: http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback. With a bit of debugging you will find out that `this` doesn't refer to what you think it does. – Felix Kling Jun 12 '14 at 22:11
  • Thanks so much, I changed all `this` into `self` which is simply `var self = this` and it works perfectly now ^^ – Yemto Jun 12 '14 at 22:23
  • The following answer could be of use to you.http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 – HMR Jun 13 '14 at 01:46

1 Answers1

0

I'll get to the networking, but I'd like to take a minute to explain a few things about JavaScript.

First off, JavaScript has no notion of classes in the traditional sense. Every object in JavaScript has a prototype that allows that object to access foreign properties as though they were properties of that object. For example, var point = {x: 0, y: 10} creates a variable point referencing an object with two local keys x and y, but point also has prototype properties that can be accessed (e.g., point.hasOwnProperty is a function from Object.prototype — which is common to most JavaScript objects). The this keyword is were things gets interesting. Whenever a function is called, the this keyword refers to the object that "owns" that function. If I did something like point.incrementX = function () { this.x++; } the this would refer to point because it "owns" the incrementX function. JavaScript allows you to override this ownership by calling .call on a function an supplying a an object to use as this inside the body of the function. Constructors are where JavaScript really confuses things. When the new keyword is applied to a function it does two things. First it constructs an object whose prototype is set to the prototype property of the constructor function. Then it supplies that object to the constructor as this. So really when you do var obj = new Constructor() its like doing var obj = Object.create(Constructor.prototype); Constructor.call(obj) (Object.create creates an object whose prototype is set to the supplied object).

Anyhow, back to the point. Instead of creating methods for your PageLoader object inside the constructor, consider putting them in the prototype property of PageLoader.

PageLoader.prototype = {
   start: function () { ... },
   stop: function () { ... }
};

// or

PageLoader.prototype.start = function () { ... };
PageLoader.prototype.stop = function () { ... };

The other thing — likely the reason your code isn't working — is the use of this inside the onreadystatechange event callback. When you used this it was actually referring to the xml variable instead of the PageLoader instance. To fix this simply put a variable declaration such as var self = this; above the xml.onreadystatechange callback.

-- EDIT --

Admittedly my explanation this was a bit weak. If you'de like a more description explanation please checkout the MDN page (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this).

Ethan Lynn
  • 1,009
  • 6
  • 13
  • *"If I did something like `point.incrementX = function () { this.x++; }` the `this` would refer to point because it "owns" the `incrementX` function."* That is not very precise. The definition doesn't determine at all which value `this` refers to. It's only determined by *how* the function is called (unless you `.bind()` it). So in your short example, you can't make any statement about the value of `this`. It will on;y refer to `point` if it's called with `point.incrementX()`. If you do `var foo = point.incrementX; foo();`, then `this` will refer to `window`. – Felix Kling Jun 13 '14 at 03:58
  • @FelixKling I understand, I was trying to keep things simple. I'll update my answer. – Ethan Lynn Jun 13 '14 at 18:43