Skip Navigation code drift

AJAX Scope in Prototype.JS

written  &  updated
in Code, but also JavaScript
🆕
2020-02-23: This was rescued from the archives of the old felocity.org. As a result, many links in this piece were left pointing to archive.org destinations.

I haven't seen this covered much, but I really felt it was worth a mention. A lot of people have worked with the prototype library, including myself. One of the most challenging things I've had to do was create an object that could make an AJAX request, and then internalize the response. Calling a function out on the global scope is messy and in poor taste if you can avoid it. I thought back to my Java classes, and remember an almost reflexive style of programming. About an hour later (including reading through prototype's source) I had a working model.

The major players in this design are the XMLHttpCatchobject and the Ajax.Request object. Our goal is to call a sending function inside of an instance of myObj, and then have the response be ran in the context of myObj. By default, you cannot refer to this inside of the callback, because of scope issues. The solution is to encapsulate the request, and then have a way for the response to find its way back home. We do this by passing the scope down into the XMLHttpCatch object. Hopefully other people will find this useful, as occasionally it is not practical to have globally scoped functions for onComplete, and you want access to all the proper this.methodName() calls. I thought about moving the catch object into myObj as a function definition during initialize, but the current model is a bit more reusable.

Abstract.XMLHttpCatch = Class.create();
Abstract.XMLHttpCatch.prototype = {
  initialize: function (opts) {},
  receive: function (response, scope) {
    scope.receive(response);
  },
};

Abstract.myObj = Class.create();
Abstract.myObj.prototype = {
  initialize: function (opts) {
    for (var prop in opts) {
      this[prop] = opts[prop];
    }
    this.XMLHttpCatch = new Abstract.XMLHttpCatch();
  },

  receive: function (response) {
    this.response = response.responseText;
    alert("Response Text: " + this.response);
  },

  send: function () {
    // get a local name for our catch object
    XMLHttpCatch = this.XMLHttpCatch;

    // get a local name for "this" (what we want to run the response under)
    scope = this;

    // prototype does the rest
    ajax = new Ajax.Request(
      "http://www.myurl.com/path/to/my.php", // URL
      {
        // options
        method: "get",
        onComplete: function (resp) {
          XMLHttpCatch.receive(resp, scope);
        },
      }
    );
  },
};

example = new Abstract.myObj();
example.send();