Access data from ajax success in complete? - javascript

Is there a way that I can access the data I receive during success so i can use it during the complete callback?
Or perhaps there is a way where i can assign multiple success functions?
What i need is, to allow success callback to be changed based on situation, but I need to always perform a dedicated function on success using the same data that was returned to the first function.
I suppose i can always setup my call like so, but i'm looking to see if there is a better way.
CallServer = function(options) {
if(options.success) {
var customSuccess = options.success;
options.success = function(data) {
defaultSuccess(data);
customSuccess(data);
}
}
$.extend(true, defaults, options);
$.ajax(defaults);
}
EDIT: I have found my answer. I didn't realize that the xhr holds the data as the responseText. so the following gets me the same thing that gets returned as 'data' on success.
complete: function(xhr){dosomething(xhr.responseText);}
and that's it! Thanks

In jQuery, the success callback accepts the data as its first argument.
From the jQuery Documentation ( http://api.jquery.com/jQuery.ajax/ ) the argument list for the success callback is:
success(data, textStatus, jqXHR)
As far as I am aware, there is no built-in way to add multiple success callbacks, but you could easily dispatch any number of functions from a custom success callback.
Perhaps you could use a system like:
function customSuccess(data) {
if (situation == "one way") {
firstFunction(data):
}
else if (situation == "another way") {
secondFunction(data);
}
}

I have found my answer. I didn't realize that the xhr holds the data as the responseText. so the following gets me the same thing that gets returned as 'data' on success.
complete: function(xhr){dosomething(xhr.responseText);}
and that's it! Thanks

Related

Jquery Pjax - Ajax success function

Currently I am translating my ajax calls to regular $.pjax() call. Everything works fine but ajax success function. I can't manage how to call pjax success function with given parameters.
The only thing I can use is defining pjax global success function to be called on each pjax call:
$(document).on('pjax:success', function(event, data, status, xhr, options) {
});
But unfortunately I would like to define per call specific success function.
Ajax call example:
$.ajax({
url:"/myPage/myFunction",
type:"POST",
data:giveMeData(),
success:function(data){$('#right_form').html(data);console.log('Success works!')}
});
Pjax call example:
$.pjax({
url:"/myPage/myFunction",
type:"POST",
container:'#right_form',
data:giveMeData(),
success:function(){console.log('Success works!')}
});
I don't believe that the jQuery PJAX library supports passing a "success" function directly in to a $.pjax call, although I suspect you could work around this using the $(document).on('pjax:success') callback & its options attribute in order to achieve the same functionality.
For example, say your request is like the above, but you want to have a custom success callback you could use something like this:
$.pjax({
url:"/myPage/myFunction",
type:"POST",
container:'#right_form',
data:giveMeData(),
custom_success:function(){console.log('Custom success works!')}
});
Then, in order to run the custom_success method you could hook up the standard pjax success listener, and given that all the parameters provided to $.pjax are made available in options, you can then grab custom_success function and run it. So your listener may look something like example
$('#right_form').on('pjax:success', function(event, data, status, xhr, options) {
// run "custom_success" method passed to PJAX if it exists
if(typeof options.custom_success === 'function'){
options.custom_success();
}
});
Which i *think* would provide the sort of functionality your after?
A late answer but I found the solution here.
$.pjax({
url:"/myPage/myFunction",
type:"POST",
container:'#right_form',
data:giveMeData(),
}).done(function() { console.log('Success works!') });

How Do I return a javascript variable from a function that contains a $.get() request

I've tried Googling this but could not reslove it. It may seem like a really simple issue to others but I'm baffled by it. I have the below code in which I get undefined for the first alert but I still get the correct values in the 2nd alert. BUT if I comment out the first alert (just the line with alert) then the 2nd alert output becomes undefined. Can any one explain why this is and how I may output the 2nd alert correctly without the first one, any Help is greatly appreciated.
function getDetails(ID){
var qArray = [];
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
});
//First Alert
alert("-> "+qArray[0]);
return qArray;
}
This is the 2nd alert which calls the above method:
var myArray = getDetails(4);
alert("myArray [0]: "+myArray[0]);
You can't return a value, the $.get() call is asynchronous.
You need to defer any operations on qArray until the AJAX call has completed, i.e. inside the callback.
Better yet, use deferred callbacks:
function getDetails(ID) {
return $.get('get_Question', {"Id":ID})
.pipe(function(json) {
return [json.value1, json.value2];
});
}
The .pipe deferred function creates a new promise which will ultimately return the desired array, but only once the AJAX call has completed.
You would then use this like this:
getDetails(ID).done(function(qArray) {
alert("-> " + qArray[0]);
});
Note that $.get() doesn't directly support error callbacks, but with deferred objects you can get access to them:
getDetails(ID).done(function(qArray) {
alert("-> " + qArray[0]);
}).fail(function(jqXHR, textStatus, errorThrown)) {
alert("The AJAX request failed:" + errorThrown);
});
Without this you'd need to build the error handling directly into the getDetails() function and then require some mechanism to tell the rest of the application logic about the error.
NB I've assumed that you don't really need to call JSON.parse() manually - if your web server returns the right Content-Type header then jQuery will do that for you automatically.
Ajax calls happens asynchroniusly, meaning you can't wait for the call to return and get the value. The way to do it is to employ a callback. Your example will become something similar to this:
function getDetails(ID, callback){
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var qArray = [];
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
callback(qArray)
});
}
Calling it will change a bit:
getDetails(4, function (myArray) {
alert("myArray [0]: "+myArray[0]);
});
The First Alert is called before the ajax call is finished, so the variable is still undefined.
This is because the $.get() is done asynchronously. There is no option for $.get() to pass parameter for async calls, so you should use $.ajax() instead and pass a param async: false
The $.get call creates a new asynchronous request for the resource in question.
When you call the first alert it is undefined because the request hasn't been completed yet. Also since you are forced to pause on the alert the request has time to be completed in the background. Enough time for it to be available by the second alert.
The same thing happens when you comment out the first alert. This time the second alert is called before the request is completed and the value is undefined.
You need to either make your requests synchronous or consider continuing execution after receiving the response by using a callback function within the success callback function you have already defined in $.get.
As several others have said, ajax-request are asynchronous. You could however set the async property to false to get a synchronous request.
Example:
function getDetails(ID) {
var result = $.ajax('get_Question', {
async : false,
data : { 'Id' : ID }
});
// do something with the result
return result;
}
I myself would have use a callback function instead beacuse async:false is bad practice and is also deprecated.
You'll need to rewrite $.get to use $.ajax and specify async: false
AJAX is asynchronous: you can't tell when the request will complete. This usually means you need to pass callback methods that will be called with the result of the request when it completes. In your case this would look something like:
function getDetails(ID, callbackFunc){
$.get('get_Question', {"Id":ID}, function(){})
.success(function(data){
var qArray = [];
var json = $.parseJSON(data);
qArray.push(json.value1);
qArray.push(json.value2);
callbackFunc(qarray);
});
}
getDetails(4, function(qArray) {
alert("myArray [0]: "+qArray[0]);
};

jquery get call complete function not working

I have a web application that gets data with a get call. When it is called, it sets a static variable. After the call is complete I want to get the value, but the complete function that I call is not working, its calling it to fast because its null.
$.get('../Controls/myfullcontrol.aspx', {}, function (data) {
$('#SiteFullControl').html(data);
}).complete(function () {
$('#FullControlCount').html('Full Control (<%=GlobalClass.GlobalVariables.User.Count %>)');
$('#LoadingAjax').dialog('close');
});
Using Firebug or Chrome's Inspector, look at the XHR and ensure that the script is actually returning something.
Are you looking for data returned to the complete function?
Then you need a parameter in the function:
}).complete(function (data) {
You don't need the $.complete() method because the $.get() contains allready an success callback.
http://api.jquery.com/jQuery.get/
You could work with jQuery the Promise interface (introduced in 1.5).So you can chain multiple callbacks on a single request...
Take look: http://api.jquery.com/jQuery.get/#jqxhr-object
jQuery.get( url, [data,] [success(data, textStatus, jqXHR),] [dataType] )
$.get('ajax/test.html', function(data) {
//STUFF AT SUCCESS
});

Trigger a function only after the completion of multiple AJAX requests

I've got a particular function I want to run once, and only after the completion of several AJAX requests.
My current solution looks a bit like this:
function doWork() {
//This is the function to be run once after all the requests
}
//some tracking/counting variables
var ajaxDoneCounter = 0;
var numOfAjaxRequests = 5;
var workDone = false;
function doWorkTrigger() {
ajaxDoneCounter++;
if( !workDone && ajaxDoneCounter >= numOfAjaxRequests ) {
workDone = true;
doWork();
}
}
// ...
//and a number of ajax requests (some hidden within functions, etc)
//they look something like this:
$.ajax({
url: "http://www.example.com",
dataType: "json",
success: function( data ) {
//load data in to variables, etc
doWorkTrigger();
}
});
One obvious pitfall in the above is that any AJAX call that is not successful will not increment ajaxDoneCount and so doWork() will probably never be called. I can get around that using the error callback in inside any $.ajax, so that doesn't worry me too much.
What I want to know is whether the above is safe and/or good practice?
Is there a trick I've missed, or any thing else that might work better?
Update: Since jQuery 1.5, deferred objects [docs] provide a cleaner solution. Have a look at an example here.
I would use .ajaxComplete(), it will be triggered whenever an Ajax call completed (success or error):
var numOfAjaxRequests = 5;
$(document).ajaxComplete(function() {
numOfAjaxRequests--;
if(!numOfAjaxRequests) {
doWork();
}
});
Then you don't have to edit every Ajax request.
You could even use .ajaxSend() to get notified of starting Ajax requests, instead of hardcoding it (but I am not sure whether this really works, maybe you will experience race conditions):
var numOfAjaxRequests = 0;
$(document).ajaxSend(function() {
numOfAjaxRequests++;
});
I think you should use complete(XMLHttpRequest, textStatus) ajax event instead of success(data, textStatus, XMLHttpRequest).
According to jQuery help:
complete(XMLHttpRequest, textStatus)
A function to be called when the
request finishes (after success and
error callbacks are executed). The
function gets passed two arguments:
The XMLHttpRequest object and a string
describing the status of the request.
This is an Ajax Event.
I don't know enough about JavaScript internals, but there is a danger that the operation:
ajaxDoneCounter++;
is not atomic. If that is the case, then this could be subject to a race condition.

Does jQuery support reading JSON from X-JSON HTTP headers?

Is jQuery able to read JSON data from X-JSON HTTP headers returned by the server? I've been searching through the jQuery docs, but all the examples I can find use JSON returned in the request body rather than the headers.
Yes, you need to call the getResponseHeader method of the XMLHttpRequest object, and do the JSON de-serialization manually:
function getHeaderJSON(xhr) {
var json;
try { json = xhr.getResponseHeader('X-Json') }
catch(e) {}
if (json) {
var data = eval('(' + json + ')'); // or JSON.parse or whatever you like
return data
}
}
Note that the try/catch is for some versions of Firefox where if the header is not present an error is thrown. I can't remember which version(s) were affected.
You have a couple ways to get a reference to the XMLHttpRequest object in jQuery:
hook into the complete callback of the ajax request, as opposed to the expected success callback (jQuery is kind of inconsistent wrt to what args are passed in what order to what callback function or global ajax trigger):
$.ajax({
// ...
complete: function(xhr) {
var data = getHeaderJSON(xhr);
// do with data as you wish
}
})
Alternatively you can save a reference to the XMLHttpRequest object returned to you from calls to .ajax/.get/.post etc, via a Closure. This allows you to use it inside whatever callback you choose (ie success or complete, or error for that matter):
var xhr = $.ajax({
// ...
success: function() {
var data = getHeaderJSON(xhr); // access xhr var via closure
// do with data as you wish
}
});
So to answer your title directly: no, jQUery obviously doesn't support this OOTB.
as of 1.4 jQuery's success: callback receives XMLHttpRequest -- (data,textStatus,XMLHttpRequest). So you don't have to use the complete: callback anymore, as laid out above.
Wish I could reply to the previous answer instead of adding a new answer.

Categories

Resources