0

I am learning to use objects and prototypes in JavaScript. I am using ajax to build an async web service. I don't want to repeat my ajax call everywhere I need it as that is inefficient and prone to error. The object below seems to work, i.e. I can access prototype properties and functions in the new object I've created, but I cannot set any properties or call any methods within the ajax function.

I want to set the "result" property to whatever the server returns to the ajax call. It's coming up either blank (the initial value given to "result") or undefined. If I alert the result directly in the ajax function it gives me the value from the database I expect. Why won't it set the prototype property?

function ajaxCall(method,datatype) {
this.method = method;
this.datatype = datatype;
this.result = '';
this.input = '';
this.error = '';
}

ajaxCall.prototype = {  
    constructor: ajaxCall,
    execQuery:function (input) {
        var self = this;
        $.ajax({
        url     : 'path/to/server/side',
        type    : 'post',
        dataType: this.datatype,
        data    : input,
        success : function(data) {
                  self.setResult(data);
                },
        error   : function(jqXHR, exception) {
                msg = someErrorFunction();
                self.error = msg;
                self.setResult(self.error);
                }
        });
    },
    setResult:function(data) {
        this.result = data;
    },
    getResult:function() {
        return this.result;
    }
};

This is how I am using the prototype. I am attempting to send a bank account number to the database and get the last reconciled balance as a json object (rec.bal). The end result is always undefined or just blank.

var data = ({"bankno": $('#bankno').val() });
//gets the account number to send to the server
rec = new ajaxCall('getBankRec','json');
//specifies the php class method on the server side and the return type
rec.execQuery(data);
var result = rec.getResult(); 
alert(result.bal);
alert(result);

Edit

I understand the issue now, and I've re-written things to include a Promise feature to deal with the timing of the ajax reqest, but it's still not working. My updated code is below:

function ajaxCall(method,datatype) {
    this.method = method;
    this.datatype = datatype;
    this.result = '';
    this.input = '';
    this.error = '';
}

ajaxCall.prototype = {  
    constructor: ajaxCall,
    execQuery:function (input) {
        var obj = new Promise(function (resolve, reject) {
        $.ajax({
            url     : '/path/to/server/side',
            type    : 'post',
            dataType: this.datatype,
            data    : input,
            context : this,
            success : function(data) {
                    resolve(data);
                    },
            error   : function(jqXHR, exception) {
                    var error = someErrorFunction
                    reject(error);
                    }
            }); //end of ajax request
                
        }); //end of Promise
        return obj;
    },
    getResult:function(promiseObject) {
        promiseObject
        .then(function (result) {
            return result;
        })
        .catch(function (error) {
            return error;
        });
    }
};

Implementing the prototype:

 $(document).ready(function() {
    var data = ({"bankno": $('#bankno').val() });
    rec = new ajaxCall('getBankRec','json');
    var promiseObject = rec.execQuery(data);
    var result = rec.getResult(promiseObject); 
    alert(result.bal);
    alert(result);
    });

'result' is still coming up undefined in the console, however the alert isn't working now. Any ideas?

Edit

I wanted to return to this and post the solution I found for the benefit of others. What worked for me was to assign the promise object to a variable (promiseObject) and use a ".then" method on it to make use of the returned value. Below is the working code.

    var data = ({"bankno": $('#bankno').val() });
    rec = new ajaxCall('ajax','getBankRec','json');
    var promiseObject = rec.execQuery(data);//promise object assignmnt
    promiseObject.then(function(value){ //then function
        $('[name="lastrecbal"]').val(value.bal); //do stuff with result
        checkClearedAmount(); //do stuff with result
    });
halfer
  • 19,824
  • 17
  • 99
  • 186
SuperCatchyUsername
  • 375
  • 1
  • 5
  • 14
  • 2
    An ajax request is **async**, so at the time you call `alert(result.bal)` or `alert(result)` the request was not done yet, and therefore nothing was set. – t.niese Sep 20 '17 at 13:51
  • I wondered about that. How would I get around that? Is there a way to tell the new object when the ajax request is done before proceeding? Perhaps some kind of while loop? – SuperCatchyUsername Sep 20 '17 at 13:52
  • The linked duplicates explain what kind of methods you could use (callbacks, promises, async/await) – t.niese Sep 20 '17 at 13:53
  • OK, I'll have a read. Thanks everyone! I'll let you know what works when i have a chance to test it later. – SuperCatchyUsername Sep 20 '17 at 13:55

0 Answers0