0

I am writing a Javascript Library which has the following code:

Constructor (Creating intial keys and creating a XMLHTTP Request object):

function hrce(key) {    
    var about = {
        Version: 0.1,
        Author: "AAA",
        Created: "Spring 2014",
        Updated: "March 2014"
    };

    if (key) {

        this.xhr = "";
        this.xhrdata = "";
        this.xhrmethod = "";
        this.xhrurl = "";
        this.xhrquery = "";

        //init with the current avaliable information
        this.key = key;
        this.protocol = "http:" === document.location.protocol ? "http://" : "https://";
        if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
            this.xhr = new XMLHttpRequest();
        }
        else {// code for IE6, IE5
            this.xhr = new ActiveXObject("Microsoft.XMLHTTP");
        }

        return this;
    } else {
        // No 'id' parameter was given, return the 'about' object
        return about;
    }
};

Here are my Library functions:

hrce.prototype = {
    load: function() {
        if (this.xhr && this.xhr != "" && this.key && this.key != "") {
            this.xhrdata = [{"access_key": this.key}];
            this.xhrurl = this.protocol + "localhost/hrce/v1/action/hsio/";
            this.xhr.onreadystatechange = this.initilizer();
            this.xhr.open("POST", this.xhrurl, true);
            this.xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            this.xhrquery = "access_key=" + this.key;
            this.xhr.send(this.xhrquery);
        }
        return this;
    },
    initilizer: function() {
        if (this.xhr.readyState == 4 && this.xhr.status == 200)
        {
            console.log(this.xhr.responseText);
        }
    }
};

now if i call for example: hrce("f07c7156").load(); Ajax call goes successfully but its not calling my this.xhr.onreadystatechange = this.initilizer(); call in load prototype function. Whats wrong in it?

25
  • 2
    It should be this.xhr.onreadystatechange = this.initilizer;, reference the function, not call it! Commented Mar 13, 2014 at 21:00
  • 1
    You're using a pattern that doesn't really work well with this kind of functionality, where you need access to the XHR object all along the way, and you're splitting it up in prototypes and what not. The solution to the current problem would be to either change the value of this with bind, call or apply, or to reference the object inside the callback, and not this. Commented Mar 13, 2014 at 21:11
  • 1
    Something like this...jsfiddle.net/TRNCFRMCN/Kk2E3 Commented Mar 13, 2014 at 21:34
  • 2
    @dollarVar - exactly, but I think call() would also call the function right away, and not when the event happens, so an anonymous function would probably be neccessary, something like this -> jsfiddle.net/Kk2E3/1 Commented Mar 13, 2014 at 21:37
  • 1
    What do you mean with "Request is gone successfully" but "it's not working"? Does @HMR's solid solution solve it? Commented Mar 14, 2014 at 0:20

1 Answer 1

2
  1. You're not using the function as a constructor.
  2. You're not assigning a bound function or passing a closure to onreadystatechange.

For the first one you have to decide, do you want the function to return an object or do you want the function to work as a constructor function. If you want a constructor then see the sample code below (I capitalized the function name as constructor functions should start with a capital).

For the second one you have to pass a closure or use bind, I use passing a closure in sample below.

function Hrce(key) {
  var about = {
    Version: 0.1,
    Author: "AAA",
    Created: "Spring 2014",
    Updated: "March 2014"
  };

  if (key) {
    this.xhr = "";
    this.xhrdata = "";
    this.xhrmethod = "";
    this.xhrurl = "";
    this.xhrquery = "";

    //init with the current avaliable information
    this.key = key;
    this.protocol = "http:" ===
            document.location.protocol ? "http://" : "https://";
    if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
      this.xhr = new XMLHttpRequest();
    }
    else {// code for IE6, IE5
      this.xhr = new ActiveXObject("Microsoft.XMLHTTP");
    }
    //constructor funcitons do not need to return this
    return this;
  } else {
    // No 'id' parameter was given, return the 'about' object
    return about;
  }
}
;

Hrce.prototype = {
  load: function() {
    if (this.xhr && this.xhr != "" && this.key && this.key != "") {
      this.xhrdata = [{"access_key": this.key}];
      this.xhrurl = this.protocol + "localhost/hrce/v1/action/hsio/";
      //note that initilizer returns a function that has a closure
      //  scope with the current instance
      this.xhr.onreadystatechange = this.initilizer(this);
      this.xhr.open("POST", this.xhrurl, true);
      this.xhr
        .setRequestHeader("Content-type"
        , "application/x-www-form-urlencoded");
      this.xhrquery = "access_key=" + this.key;
      this.xhr.send(this.xhrquery);
    }
    return this;
  },
  initilizer: function(me) {
    //returning a function used as closure
    // the variable me is the current instance of Hrce
    return function(){
      if (me.xhr.readyState == 4 && me.xhr.status == 200)
      {
        console.log(me.xhr.responseText);
      }
    }
  }
};

var connector = new Hrce("f07c7156");
connector.load();

More info about constructor functions, prototype and what the this variable represent can be found in this answer.

Sign up to request clarification or add additional context in comments.

6 Comments

Perfect! Thats what i was looking for thanks mate for the answer and specially the link of your answer in which you gave the introduction of the Prototyping.
Hey, nicely done (plus one;). He was calling it with new at first, because the whole thing would not have worked like this (wanted to comment on that first). However, do you know why @adeneo's solution didn't "work" in the end?
@dollarVar The code works but the site doesn't allow POST request or the header. You can see the request fail in firebug or Chrome (press F12). Changed the POST to this.xhr.open("GET" and commented out this.xhr.setRequestHeader("Content-t... Then it works. His code is basically the same as mine but he creates a closure with an anonymous function and that can trap large variables you never use.
@HMR One more question i have. If i use your implementation. Here is the fiddle: jsfiddle.net/g6Qeb/1 . Now my Question is that i am calling the function of track of Hrce. In your answer i set the cookie in the intilizer function. i call track right after that load but it doesn't get the cookie. But if i call track on console separately it works. What is the missing point ? am i not using the inheritance correctly?
@PHPSeeker A quick look at the code let me think you assume the xhr request is synchronous. When you call load the xhr request is made but when you call track the load request is almost certainly not finished yet so the cookie hasn't been set yet. You can use callbacks, promises or use a mediator to solve this. The easiest way would be callback, the most maintainable would be promise or mediator but that's kind of complicated.
|

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.