Javascript return reference to jqXHR from function - javascript

Recently I abstracted a bunch of AJAX calls into a function using the $.post() method. My idea was to use the jqXHR object returned by $.post() to add standard error handlers and such (via .fail() .done() .always()) to remove code duplication. I then thought that I could return the jqXHR object from the method to the original calling function so I could add additional handlers to do more context-specific things.
However, the jqXHR object returned seems to be a copy of the original object, not the object itself. As such, its state never gets updated by the original call so none of my additional .done() functions get executed.
Is it possible to return a reference to an object in JS? I have a C++ background, so is there a way to mimic the "return pointer to object" functionality in JS?
I know there have been discussions on pass-by-reference/value on here, but I couldn't find one dealing specifically with Deferred objects
EDIT: example code
function AJAX(url,data,onSuccess) {
var jqxhr = $.post({url,data});
jqxhr.done(onSuccess);
jqxhr.fail(displayError());
return jqxhr;
}
...
function example() {
var dfrd = AJAX("example.php",data,successFunc);
dfrd.done(alert("Hello, World!"));
}
The .done() & .fail() within the AJAX function get executed normally, but the .done() within example() never executes because dfrd.state() is always pending

So this turned out to be a timing issue.
It appears that, with multiple .done() functions, there is a slight delay when the function receives a response from the $.post() call. So my onSuccess(resp) {} that was passed to the AJAX function would execute after the alert(). The particular onSuccess function I was using to test had a page refresh call in it, which would close the alert before I could see it.
I have a C++ background, so I guess I need to upgrade my JS testing procedures.
Thanks to all who commented!

Related

Issue with multiple ajax calls simultaneously using jquery

I am using jquery for ajax calls
All the calls are called immmediately on page load and we are getting the responses at almost the same time.
the issue is, the 3 calls are fired and I am getting the data, but the callback function is fired for the first call only.
the other two callbacks are not called, the callback is defined as a separate function,
If I just write an alert instead of calling the callback method, all the 3 alert message are coming
So the issue is when we write the callback method, do any one have any idea of the strange behaviour?
We tried to reorder the calls, the behaviour is similar, which ever is called first, its callback will be called, for the rest, it will not be called
var url = "/test1";
ajaxCall(url, testMethod1, false);
var url = "test2";
ajaxCall(url, testMethod2, false);
var url = "test3";
ajaxCall(url, testMethod3, false);
testMethod1:function(data){
console.log("first"+data);
},
testMethod2:function(data){
console.log("second"+data);
},
testMethod3:function(data){
console.log("thrid"+data);
}
ajaxCall is defined as jquery ajax, the issue is only the testMethod1 is called, the rest 2 are not called
Regards
Hari
Well the thing that immediately caught my eye is that the URL for test1 has a forward slash preceding test1. This means that you are using a valid link in only test1. The alerts will trigger because you are probably not trying to access the data returned (which would still work even though the ajax request fails), where as you are trying to access the data in the coded call back functions you have provided, which will obviously throw a NullPointerException or whatever the equivalent as the ajax call fails due to an incorrect URL. Therefore data never gets set and the code doesn't work.

$.ajax() callbacks are not bound to their specific request?

The code is very complex so i have simplified below in order to confirm if the behavior i am experiencing is normal or due so some other error i have made in the code.
I have two separate ajax requests that each have their own unique call back. I do not care which one completes first and one has no dependency on the other
function ajax(url, cbS){
$.ajax({
url: url,
contentType: 'application/json',
dataType: 'json',
success: function(data){
cbS(data)
},
});
}
function callbackSuccess1(data){
$('#div1').html(data)
}
function callbackSuccess2(data){
$('#div2').html(data)
}
//request#1
ajax(myapiurl+'&peram1=100', callbackSuccess1);
//request#2
ajax(myapiurl+'&peram2=200', callbackSuccess2);
The problem: Sometimes callbackSuccess1 gets the data intended for request#2 and vice versa.
It seems that which ever request completes first fires callbackSuccess1 and the second to complete fires callbackSuccess2.
I need the callback to be bound to it's specific request so that regardless of the order in which they complete each request fires it's proper callback.
OTHER INFO: My backed is django-tastypie, at this point i am thinking that tastypie is somehow messing up the response. That is the only logical conclusion, given that the javascript seems to be immutable.
The proof that this is actually occurring is that when i inspect the responce on request#1 the data objects are clearly intended for request#2...
CONCLUSION:
Thanks for confirming that 'each invocation of your ajax() function will create it's own closure'. This was what i thought was going wrong. I found the problem in my API. I was doing some funky stuff and it looks like I had a variable that was not getting trashed in time causing the API to return the wrong data if the first request took longer than the second.
The only issue I see with the code you have included is that the function argument is cbS, but you are calling cbs(data) - note the different capitalization.
Other than that, each invocation of your ajax() function will create it's own closure and have it's own arguments and those arguments will be preserved separately for the internal success callback. This is an important capability in javascript and it works. It does not get the arguments of one call confused with the callback of another as long as you are not using any global variables or state that might change during the execution of the asynchronous ajax call.
You could probably use jsonp and specify callback query parameter in URL for $.ajax
callback would be the name of javascript function which is to be invoked whenever the response is returned from server.
For more details please refer jquery doc : http://api.jquery.com/jQuery.ajax/
For theory : http://en.wikipedia.org/wiki/JSONP
This is mainly used for cross-site ajax calls.

When to assign functions to variable, using jquery

so I've been messing around with some Jquery Ajax promises/deffers etc... and i've come across something I don't completely understand, not strictly related to the Jquery Ajax.
I have always declared and called functions like so:
function foo1() { //sets function
alert('foo1');
}
foo1(); //calls function
But it seems the more I see different code a lot of people are declaring functions like the following, I just copied and pasted an example I saw so I would't miss anything:
var promise = $.ajax({
url: "/myServerScript"
});
promise.done(myStopAnimationFunction);
I understand what the above does, just an example.
The question is, is it better to assign functions to variables? What are the pros/cons, and in what situations is this way used?
At what point in this code is the actual function called. Does
promise.done(myStopAnimationFunction);
call both the ajax function, and then the callback, or just the callback?
Thanks
In your example, you're assigning your promise variable to what $.ajax returns (which is a jqXHR object)
var promise = $.ajax({
url: "/myServerScript"
});
Your then saying that once it's done, you want to call myStopAnimationFunction. Because $.ajax is async by default, the browser will skip right over this and only call your myStopAnimationFunction when the request is complete.
promise.done(myStopAnimationFunction);
Now, with your myStopAnimationFunction; you could always just do the following:
promise.done(function(){
$('.loader').hide();
});
but if you have code which you'll be using a lot, put it in a function so you don't need to repeat yourself (see DRY) - this has nothing to do with jQuery, however.
Your example is exactly the same as doing:
$.ajax({
url: "/myServerScript"
}).done(function(){
$('.loader').hide();
});
Those are two very different things! The first one is a function declaration. The second one is a function invocation, and what is assigned to the promise variable is the value returned by the function you're calling ($.ajax).
In any case, it is possible to assign functions to variables too (but I'm not sure if that's what you're really asking – if it is, this is a duplicate of var functionName = function() {} vs function functionName() {}).
Does promise.done(myStopAnimationFunction);
call both the ajax function, and then the callback, or just the callback?
Neither. That line is a call to done on the promise object, to register a callback to be called when the ajax response arrives. At that point you call done, the ajax request may have already fired, and the response even might already be available (if that's the case, the callback will be called immediately).

jquery ajax return value and done function

I found this little example on jquery documentation page. I always tried returning value from ajax function and I was always told that there is some problem of sync and async thing and I can't return value out of $.ajax function without making it async.
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
$(this).addClass("done");
});
In the example above, on what this done function is applied(whats being used as $(this) in example).
one more thing, as the ajax function can't set global variables, can't the be set in this done too? cant I return value out of done function either?
what this done function is applied
$.ajax returns a jqXHR object (see first section after the configuration parameter description) wich implements the promise interface and allows you to add callbacks and get notified of changes of the Ajax call.
whats being used as $(this) in example
Inside the callbacks for $.ajax, this refers to the object context refers to in the configuration or the jqXHR instance if context was not set. In this case it refers to document.body:
context: This object will be made the context of all Ajax-related callbacks. By default, the context is an object that represents the ajax settings used in the call ($.ajaxSettings merged with the settings passed to $.ajax).
This and more is all explained in the documentation: http://api.jquery.com/jQuery.ajax/
as the ajax function can't set global variables
That is not correct, any function can set global variables. The problem with asynchronous functions is that you are likely accessing the variable before it was set.
can't the be set in this done too
See above
cant I return value out of done function either
You can return a value (as in putting a return statement inside the callback), but you cannot return it to your code, since jQuery is calling the callback internally and just ignoring the return value.

Run code after black box AJAX request returns

I have a function which makes an AJAX request to a server and returns relevant information after it completes.
I have another function which manipulates some variables in its namespace based on the returned information.
Currently, I am appending a 'callback' argument to the first function, which is called when the request completes. This, however, blurs the purpose of the first function - instead of being a 'getInfo' function, it's become a 'getInfoAndDo' function.
Ideally, I'd like to call the second function (a 'do' function, which calls the first function, a 'get' function) and does its thing.
I have looked around and found jQuery methods such as .ajaxStop and .ajaxComplete, but they seem to only to work when bound to DOM elements. Is there any way to do this entirely in javascript?
e.g.
function _getEventAttendance(uid, callback) {
var attendQuery = FB.Data.query('SELECT eid,rsvp_status,start_time FROM event_member WHERE uid = {0}', uid);
FB.Data.waitOn( [attendQuery],
function (args){
callback(args[0]);
}
);
}
function logAttendance(attendance){
console.log(attendance);
}
Currently, I am doing:
_getEventAttendance(123456789, logAttendance);
which seems ridiculous to me.
Is there a way to write the code such that I can change the code snippet inside _getEventAttendance / remove the callback argument:
FB.Data.waitOn( [attendQuery],
function (args){
return args[0];
}
);
and then make calls that are equivalently as simple as :
logAttendance.ajaxComplete(_getEventAttendance(123456789));
(I'm just making up the syntax for this, I have no idea how it's supposed to be written.)
$.when(<AJAX Request>).then(function(response){...});
Optionally use $.pipe() to filter response first.

Categories