0

My Class looks like

function classUser() {
   var userName;
   var firstName;
   var lastName;
   var sessionid;
}

classUser.prototype.set_user_name = function (user_name) {
    this.userName = user_name;
}

classUser.prototype.set_first_name = function (first_name) {
    this.firstName = first_name;
}

classUser.prototype.set_last_name = function (last_name) {
 this.lastName = last_name;
}

classUser.prototype.get_curr_session = function () {
    return this.sessionid;
}

classUser.prototype.save = function () {

     $.ajax({
       type: "POST",
       url: "http://myapihost.com:8080/api/1.0/user/",
       data: JSON.stringify(this),
       dataType: "json",
       success: function (apiResponse) {
          var currSessionID = apiResponse.sessionId;
          this.sessionid= currSessionID;
        },
        error: function (apiResponse) {
          alert("error  : " + apiResponse);
          this.sessionid= "Error";
        }
    });
}

I call them as

    var User = new classUser();
    User.set_first_name(userFirstName);
    User.set_last_name(response.last_name);
    User.set_user_name(response.username);

    User.save();
    var currSessionID = User.get_curr_session();

Sometimes, get_curr_session is called before success: call.

Question : I tried returning sessionid from success itself so that save() function does the job. That is not working. hence i split across 2 functions.

Can I do it in one call itself? if I have use 2 functions - how do i make sure that it works all the time.

I could actually put assigning the currSessionID within success, however that breaks class sanctity. I have seen other solution like using "done", not sure if that would help here.

=======================================

I modified the code as below

classUser.prototype.save = function (callback) {

 $.ajax({
    type: "POST",
    url: "http://myapihost.com:8080/api/1.0/user/",
    data: JSON.stringify(this),
    dataType: "json",
    success: function (apiResponse) {
        var currSessionID = apiResponse.sessionId;
        this.sessionid= currSessionID;
        callback(null, currSessionID);
    },
    error: function (apiResponse) {
        alert("error  : " + apiResponse);
        this.sessionid= "Error";
        callback("error", null);
    }
});
}

When I call

User.save(mycallback);


function mycallback(error, sessId){
    if(error) {
        console.log("Some error occurred. Check code");
        return;// Something went wrong
    } else {
        console.log("Session : " + sessId);
    }
}

Is this good now?

Thanks Ajay

Thoughtful Monkey
  • 648
  • 2
  • 10
  • 24
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – Phil Oct 02 '13 at 08:05
  • I don't think those `var` declarations in `classUser` do what you think they do. – user2357112 Oct 02 '13 at 08:09
  • means? they do exactly what I want them to :) – Thoughtful Monkey Oct 02 '13 at 08:38
  • @ThoughtfulMonkey In your provided code the `var` statments in the function `classUser` have no effect on your code. They bind the variables `userName`, `firstName`, ... to the scope of the function `classUser`, but because they are not used inside of it, they are effectively useless at that point. (`var userName;` has nothing to do with the `this.userName`) – t.niese Oct 02 '13 at 08:49
  • true; however do they have any negative side effect? if no, i will keep it as it is to have readable code. – Thoughtful Monkey Oct 02 '13 at 09:35
  • 1
    @ThoughtfulMonkey no they don't have side effects, but if you want to show that/what properties you class has you should mark them in a different way e.g. using JSDoc. Or with defining a default value `classUser.prototype.userName = null;` outside of you `classUser`. Another note: I suggest to choose one naming conversation either `user_name` or `userName` mixing them often leads to errors. – t.niese Oct 02 '13 at 09:47
  • Noted :). Thank you. This is my first go at Object Oriented JS and this helps. – Thoughtful Monkey Oct 02 '13 at 09:55

3 Answers3

3

That's because the success and error function of the ajax request are executed asynchronously.

To make sure this doesn't happen, you should add a callback to your save function that is called after the success or error functions ran.

classUser.prototype.save = function (callback) {

     $.ajax({
       type: "POST",
       url: "http://myapihost.com:8080/api/1.0/user/",
       data: JSON.stringify(this),
       dataType: "json",
       success: function (apiResponse) {
          var currSessionID = apiResponse.sessionId;
          this.sessionid= currSessionID;
          callback(null, currSessionID);
        },
        error: function (apiResponse) {
          alert("error  : " + apiResponse);
          this.sessionid= "Error";
          callback(apiResponse, null);
        }
    });
}

Then, when calling the save function, you can do something like this:

User.save(function(error, sessId) {
    if(error) {
        // Something went wrong
    } else {
        // Do whatever you need to do
    }
});

You should note that this will also run asynchronously. So if you want to work with the session ID, don't do that after the User.save(...) call, but inside the function.

MildlySerious
  • 8,750
  • 3
  • 28
  • 30
  • I think this is what I need. However, where do i define callback functions? (I havent used them before). right now it says callback not defined. – Thoughtful Monkey Oct 02 '13 at 08:49
  • @ThoughtfulMonkey you pass it as parameter to your `save` function either as an anonymous function like you do at your `success`/`error` callback, your a _reference_ to an existing named function. – t.niese Oct 02 '13 at 08:55
  • I added some code. please let me know if this the correct way to go about it. – Thoughtful Monkey Oct 02 '13 at 09:44
  • My new code worked perfect on Firefox. however didn't work on chrome :( and no error also in dev console. – Thoughtful Monkey Oct 02 '13 at 10:48
0

$.ajax() issues an asynchronous call to the url specified in the options object. See the jQuery documentation at http://api.jquery.com/jQuery.ajax/

success is a callback function that is invoked when the call is completed and all the response stream is read by the browser so basically in most of the cases the callback (updating the session id) will execute after you try to retrieve it.

DenisPostu
  • 599
  • 3
  • 10
  • 1
    The `success` callback is always called after the current _execution flow_ (like writing `setTimeout(function() { .... },0);`) If it is somehow executed before the `var currSessionID = User.get_curr_session();` then i would consider it as a bug, because it conflicts in how `async` call should/do work. – t.niese Oct 02 '13 at 08:12
  • You're right. I was considering the possibility of calling `$.ajax()` with `cache: true` and thought that the browser wouldn't issue the async request but instead serve the cached version thus executing synchronously. At least this is how .NET tasks work and I extrapolated to JS promises, but I'm most probably wrong ;) – DenisPostu Oct 02 '13 at 08:16
  • Also with _cached_ it should be called after the current execution flow. [Promises/A+](http://promises-aplus.github.io/promises-spec/) `[...]this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called [...]` jQuery has various parts in the code to ensure this e.g. `// (IE6 & IE7) if it's in cache and has been retrieved directly we need to fire the callback` where they use `setTimeout( callback );` If `api` is defined as async it should always behave that way (or provide a parameter/alternative to make it sync). – t.niese Oct 02 '13 at 08:29
0

I think what is happening here is that the default ajax call is async which means that the code var currSessionID = User.get_curr_session(); can execute before the success call completes.

You have a couple of options, you can try and update your code to be more async capable, using callbacks or other methods, or specify that you want your ajax call to be synchronous.

jasonscript
  • 6,039
  • 3
  • 28
  • 43
  • You should not suggest to make the ajax call `synchronous`, because this could/will lead into bad impact on the responsiveness of the browser. – t.niese Oct 02 '13 at 08:34