Wesley Smith
Wesley Smith

Reputation: 19571

How can I send an object via Ajax from within a Javascript Class?

My question title may not be phrased well, sorry.

I want to create a Javascript class to simplify sending information to a php page.

I'm using the method described in this answer to create my class

This is what I have so far:

var ParseObject = Class.extend({
  init: function(classname, id){
    // required properties  
    this.classname=classname;
    this.objects=[];
    this.fields=[];
    // optional properties
    if(id && id != '') this.id='';
    //this.command = command;
    //this.callback='';
    //this.parent=[];
    //this.children=[];
    //this.relation='';
  },
  set: function(field, value) {
      if(field == 'classname') this.classname=value;
      else if(field == 'callback') this.callback=value;
      else if(field == 'command') this.command=value;
      else this.fields.push(field, value);
  },
  addChild: function(obj){
      this.children ? this.children.push(obj) : this.children= [obj];
  },
  addParent: function(linkedFieldName, parentClassName, parentId){
      this.parent=[linkedFieldName, parentClassName, parentId];
  },
  addObject: function(obj){
      this.objects.push(obj);
  },
  isRelatedBy: function(relation){
      this.relation=relation;
  },
  send: function(){
        var obj = this;
        $.ajax({
              type: "POST",
              dataType: "json",
              url: "php/parseFunctions.php",
              data: {data:obj},
              success: function(response) { 
                  // do stuff 
              },
              error: function(response) {
                  // do stuff 
              }
        });
  }
  
});

And here's how Im trying to use the class:

var testObject = new ParseObject('TestObject');
testObject.set('callback','testResopnse');
testObject.set('command','save');
testObject.set('title','New Title');
testObject.set('description','New Description');
testObject.set('stuff',['one','two','three']);
testObject.addParent(['parent', 'MeComment', 'kRh5xcpkhz']);
testObject.send();

Everything works as expected until I get to testObject.send();

What I expect is for the below object to get sent to my PHP page:

enter image description here

But instead, what I get is "Uncaught RangeError: Maximum call stack size exceeded"

Why does this happen, and how can I achieve the desired result?


Update:#

Per Quentin's suggestion, this got me sorted

var obj =$.parseJSON(JSON.stringify(this));

Upvotes: 1

Views: 1628

Answers (1)

Quentin
Quentin

Reputation: 943697

When you pass an object to data:, jQuery will call param on it.

That function includes this code:

 // If value is a function, invoke it and return its value
 value = jQuery.isFunction(value) ? value() : (value == null ? "" : value);

That ends up calling all the functions in the object (including the constructor) in the context of window. I don't have the tuits to figure out all the effects of that, but it clearly isn't desirable and, based on the error message, leads to infinite recursion.

You have several options here:

  1. Write an explicit function that extracts the data you care about from the object and presents as a simple data structure consisting only of the data types you can serialise with .
  2. Serialise the object to JSON and then deserialise it to strip out all the functions before you pass it to param via data:
  3. Serialise the object to JSON, pass that as a string to data:, set the request contentType: "application/json" and change the PHP to expect a JSON formatted request instead of a form formatted request.
  4. (I don't know if this will work) change the way you construct the class to use Object.defineProperty() and mark all the functions so they are not enumerable. I suspect this approach would fail because the object is, itself a function.

Upvotes: 4

Related Questions