4

I'm having some issues with returning a value from a synchronous ajax call. The value I want to return is a class I created for a server response.

Here's the AJAX code:

function webRequest(file, data) {
    return $.ajax({
        url: "http://xxx.xx.xx.xxxx/xxxxx/"+file,
        type: "POST",
        data: data,
        asynch: false,
        error: function(jqXHR, textStatus, errorThrown){
            return new ServerResponse(false, errorThrown);
        },
        success: function(data, textStatus,  jqXHR){
            return new ServerResponse(true, data);
        },
        timeout: 7500
    });    
}

Here's ServerResponse.js

var success = false;
var text = null;

var ServerResponse = function(success, text) {
    this.success = success;
    this.text = text || null;
};

ServerResponse.prototype.isSuccessful = function() {
    return this.success;  
};

ServerResponse.prototype.getData = function() {
    return this.text;
};

The returned value of webRequest(..) is as follows:

Object {readyState: 1, getResponseHeader: function, getAllResponseHeaders: function, setRequestHeader: function, overrideMimeType: function…}abort: function ( statusText ) {always: function () {complete: function () {done: function () {error: function () {fail: function () {getAllResponseHeaders: function () {getResponseHeader: function ( key ) {overrideMimeType: function ( type ) {pipe: function ( /* fnDone, fnFail, fnProgress */ ) {progress: function () {promise: function ( obj ) {readyState: 0responseText: ""setRequestHeader: function ( name, value ) {state: function () {status: 0statusCode: function ( map ) {statusText: "error"success: function () {then: function ( /* fnDone, fnFail, fnProgress */ ) {__proto__: Object VM2324 controllers.js:48

How can I return the ServerResponse instance created from within the ajax call?

Hobbyist
  • 15,888
  • 9
  • 46
  • 98
  • 1
    Do you not have the typo `asynch` in your code? (Should be `async`.) – marekful Jul 05 '15 at 15:38
  • @marekful - Correct, I did, thanks, did not change results though. – Hobbyist Jul 05 '15 at 15:40
  • *Why* are you using a synchronous AJAX call? It's bad for user experience and [jQuery's `async: false` option has been deprecated](http://stackoverflow.com/q/11448011/1233508), so unless you have a *really good* excuse for it, you should be using asynchronous calls instead. – DCoder Jul 05 '15 at 16:01
  • 1
    The #1 thing to fix here is to stop using a synchronous Ajax call and learrn how to program with async operations. The user experience will be so much better with async operations, especially if connectivity is a bit slow (like mobile or just slower internet connection). – jfriend00 Jul 05 '15 at 16:02
  • @jfriend00 - This is completely irrelevant to the question at hand. The reasoning for using a synchronous call is simply because the application cannot continue without the data. I see no reason to contaminate the code with a bunch of boolean spaghetti just to use asynchronous calls where it's not needed. Regardless as to if I used an asynchronous or synchronous call, the user is going to have to wait for the data to be received before continuing. – Hobbyist Jul 05 '15 at 16:19
  • 2
    @Christian.tucker - it is not irrelevant. What you are doing is a bad practice and can lead to a poor user experience. Good advice and good answers (which is what people should offer here) will point out when you're using a bad practice. Your code could be fixed to use an async response. It would require some restructuring, but that is the best practice for making any ajax call. If you didn't know this was a bad practice that can lead to a bad user experience, then you have now been advised of that. If you choose to ignore that advice, that is your choice. – jfriend00 Jul 05 '15 at 16:21
  • 1
    If you haven't learned how to use async responses from Ajax calls, you would drastically improve your Javascript programming skills and the quality of the code you produce by doing so. It takes a little work to learn it, but then is quite straightforward to use, particularly using the promises built into jQuery Ajax. – jfriend00 Jul 05 '15 at 16:25
  • I know how to use AJAX. Synchornous AJAX isn't even AJAX anymore, considering the "A" stands for Asynchronous. I simply stated that in the scenario that I was using the synchronous call it would not effect the user experience. I have asynchronous calls in my application and use them where I see fit, such as loading images, pulling information from facebook, and our chat system. – Hobbyist Jul 05 '15 at 16:32

1 Answers1

3

@fuyushimoya's answer is almost there, just return the newly instantiated server response object from the wrapper function.

function webRequest(file, data) {
    var serverResponse;
    $.ajax({
        url: "http://xxx.xx.xx.xxxx/xxxxx/"+file,
        type: "POST",
        data: data,
        async: false,
        error: function(jqXHR, textStatus, errorThrown){
            serverResponse = new ServerResponse(false, errorThrown);
        },
        success: function(data, textStatus,  jqXHR){
            serverResponse = new ServerResponse(true, data);
        },
        timeout: 7500
    });
    return serverResponse;
}

This way you can do

var sr = webRequest('some/file', someData);
marekful
  • 14,986
  • 6
  • 37
  • 59
  • I'm curious that in this way, when can he determined that the sr has been filled up with something? – fuyushimoya Jul 05 '15 at 15:53
  • 3
    When an AJAX call is synchronous, it blocks execution until success or error response is sent/processed. So after the expression `$.ajax({...});` you can be sure that `serverResponse` is not undefined because either success or error will be executed by then. – marekful Jul 05 '15 at 15:55
  • @fuyushimoya - That's because with the `aysnc` setting set to false, the code executes in the order it was provided. I forgot about trying this again after disabling the `async` function. This is correct. – Hobbyist Jul 05 '15 at 15:55
  • Ok, didn't notice that `async: false`, thanks for the answer. – fuyushimoya Jul 05 '15 at 15:56