objectjquery ajaxUPD success returning undefined - javascript

I have created a function called save , when i call save function, I am getting success undefined or object Object
UPDATES:
updated to get he values jqxhr object that ajax returns
function save() {
return $.ajax({
type: "POST",
url: "foo.json",
data: json_data,
contentType: 'application/json',
success: function (data, textStatus, xhr) {
$('<div id="loading">Loading...</div>').insertBefore('#form');
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
}
$(document).ready(function () {
$(function () {
$("#save").click(function () {
var jqxhr = save();
alert("success " + jqxhr.success);
alert("status " + jqxhr.status);
alert("status " + jqxhr.readyState);
});
});
});

For the upteenth time.
ajax is asynchronous.
Use a callback function.

Ninja edit by OP
First of all, there is no return statement within your save function, so it works as expected by returning undefined value.
Secondly, it won't work that way. You need to return the $.ajax call (which itself, returns a jqXHR object, where you can hook in and setup code for different events. Afterall, by default an Ajax request runs asyncronously.
in save()
return $.ajax({ ...
and later...
save().done(function( retValue ) {
alert('success ' + retValue);
});
Learn more about jQuerys Ajax and Deferred objects here and here.

May be this is causing the issue, as i see you are having 2 document ready handlers one in another.
/***/
$(function () { // <--------------------I think this doesn't has to be here,
// so remove it and try if this solves
// the issue
$("#save").click(function () {
var success = save();
alert("success " + success);
});
}); // <-------------------------------and this one too

Related

How call a callback of an Ajax function in another function

I have an Ajax function which is loading data from a webservice. It looks like this:
$.ajax({
type: 'POST',
url: back + this.path_Uri,
data: {msg:this.msg},
dataType: "json",
success: function (data, statut) {
// traitement to not execute here
window.reloadFreelancersMission= data;
var number = reloadFreelancersMission.pagination[0].pagenbr;
window.pagination.ReloadPager(number);
/////////////////////////////////////////////////
},
error: function (data) {
console.log(data);
}
});
I need to do some treatment in the result of the response of this web service in another function in another file.
My file contains a function of sending data within my ajax function. It looks like this
sendFiltres: function () {
$("body").on('change', '.filtres' , function () {
var choix_filtres = $("#fitre_recherche");
var msgJson = JSON.stringify(serializeObject($("#fitre_recherche")));
window.sendData.start(choix_filtres,msgJson);
})
},
So I need here to use the callback of my function in this way:
request.done(function( msg ) {
console.log( msg );
});
and integrate my treatment, to obtain this for:
request.done(function( msg ) {
window.reloadFreelancersMission= data;
var number = reloadFreelancersMission.pagination[0].pagenbr;
window.pagination.ReloadPager(number);
});
but it seems that I can't call this callback in this file. I'm allowed to use it only in the same file of my ajax function, and that's exactly my problem.
In my case, I resolved my problem by recuperating the response of my service within the callback function of jQuery ajaxSuccess
$(document).ajaxSuccess(function (event, xhr, settings) {
if (settings.url === window.find_mission.route.getmission || settings.url === window.find_freelance.route.getfreelance) {
xhr = xhr.responseJSON;
var pagenumber = xhr.pagination[0].pagenbr;
window.pagination.ReloadPager(pagenumber);
}
});
where I was using the xhr variable to get my data.

Calling a method after two other methods have been completed

I am looking for the best standard javascript way of monitoring when a method is completed.
I have a method used for ajax calls like this:
function rdRelatedJobs(param1,param2,param3) {
var completeURL = param1 + param2 + param3;
$.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
};
},
error: function() {
console.log("An error occurred while processing XML file.");
}
});
} // end function rdRelatedJobs
This function is called twice, queued immediately after each other. What I need to know is how to call another method once the second call to this method is complete.
Note it does not matter if the ajax request is success or failure in this case. I just need to know how to call the method once the method above is run twice.
There's a jQuery-specific answer, and a general answer.
The jQuery-specific answer is to return the result of the ajax call, which is a jqXHR object:
function rdRelatedJobs(param1,param2,param3) {
var completeURL = param1 + param2 + param3;
return $.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
},
error: function() {
console.log("An error occurred while processing XML file.");
}
});
} // end function rdRelatedJobs
...and when you're calling rdRelatedJobs, use $.when:
$.when(
rdRelatedJobs(/*...args for first call...*/),
rdRelatedJobs(/*...args for second call...*/)
).then(function() {
// both are done now
});
That works because jqXHR objects implement the jQuery Promise API, and $.when will call your callback when all of the promises you give it have been fulfilled.
The generic answer would be to use a promise library that does something similar.
Or another generic answer would be to have rdRelatedJobs call a callback when it's done, and to maintain a counter:
function rdRelatedJobs(param1,param2,param3,done) {
var completeURL = param1 + param2 + param3;
return $.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
done(xml);
},
error: function() {
console.log("An error occurred while processing XML file.");
done(null);
}
});
} // end function rdRelatedJobs
...and then:
var counter = 0;
function done(result) {
if (--counter === 0) {
// Both are done
}
}
rdRelatedJobs(/*...args for first call...*/, done);
++counter;
rdRelatedJobs(/*...args for second call...*/, done);
++counter;
That looks like a race condition, but it isn't, because there is only one main UI JavaScript thread in browsers.
outside the function you can have a `var counter`
and then inside:
$.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function(xml){
// We parse the XML here
counter++;
if(counter==2) bla bla
};
},
error: function() {
console.log("An error occurred while processing XML file.");
counter++;
if(counter==2) bla bla
}
});
function rdRelatedJobs(param1,param2,param3) {
var completeURL = param1 + param2 + param3;
// return an ajax promise from this function
return $.ajax({
type: "GET",
url:completeURL,
dataType: "xml",
success: function (xml) {
// We parse the XML here
},
error: function () {
console.log("An error occurred while processing XML file.");
}
});
}
// compile the promises by passing them into an array
function getPromises() {
var promises = [];
promises.push(rdRelatedJobs(1, 2, 3));
promises.push(rdRelatedJobs(3, 4, 5));
return promises;
}
// use $.when by passing in the promise array using the apply method
$.when.apply(null, getPromises()).then(function () {
// do a thing
});
You could use a library called Q and do an 'all' and use a 'then' with a success and failure callback
https://github.com/kriskowal/q
e.g:
Q.all([rdRelatedJobs(x,y,z), rdRelatedJobs(a,b,c)]).then(function () {
console.log("Data saved!");
});
Very similar to the jquery $.when the 'then' will only get called when both ajax requests have finished. You would have to alter the rdRelatedJobs to do a return just before the $.ajax so that the promise is returned from the function.

Get data back from ajax call within ajax call

I'm need some help figuring out how to get back data from the second ajax call, not the first.
I have this method that calls my ajax calls
var projectWithIssues = getProjects().done(function(result) {
....
}
When I look at the results from this, I get back the results on my first ajax call(getEnt_PodType().done()). I want to get the results from the second ajax call within getProjects(). I understand the reason I'm getting the first results back is because I have the return on the first ajax call. However, If I don't have a return there. I get a undefined on the line above. How can I return the data from the second call?
function getEnt_PodType() {
var ent_PodType;
var oDataUrl = //URL to my data;
return $.ajax({
url: oDataUrl,
type: "GET",
async: true,
beforeSend: function (xhr) {
xhr.setRequestHeader("ACCEPT", accept);
},
success: function (xhr, textStatus) {
}
});
}
function getProjects() {
return getEnt_PodType().done(function (res) {
var ent_PodType;
if (res.d.results != undefined) {
ent_PodType = res.d.results[0].Ent_PodType;
}
console.log("The ent pod type value is " + ent_PodType);
var QUERY_FILTER =
"$filter=Ent_PodType eq '" + ent_PodType + "'";
var url = restUrl + QUERY_FILTER;
// I want to return the results from this ajax call
$.ajax({
url: url,
type: "GET",
async: true,
beforeSend: function (xhr) {
xhr.setRequestHeader("ACCEPT", accept);
},
success: function (xhr, textStatus) {
//projects = parseODataResultTest(xhr);
//return projects;
}
});
});
}
Thanks in advance!
Try utilizing pattern found at deferred.then
// first request
var request = $.ajax(url1),
chained = request.then(function( data ) {
console.log(data) // first request response data
// return second request
return $.ajax(url2)
});
chained.then(function( data ) {
console.log(data) // second request response data
// data retrieved from url2 as provided by the first request
});
var request = $.ajax("https://gist.githubusercontent.com/guest271314/23e61e522a14d45a35e1/raw/62775b7420f8df6b3d83244270d26495e40a1e9d/ticker.json"), // first request , `html` document
chained = request.then(function( data ) {
console.log(data) // `["abc"]`
// return `data` from second request
return $.ajax("https://gist.githubusercontent.com/guest271314/6a76aa9d2921350c9d53/raw/49fbc054731540fa68b565e398d3574fde7366e9/abc.txt")
});
chained.then(function( data ) {
console.log(data) // `abc123`
// data retrieved from url2 as provided by the first request
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Use .then instead of .done, it allows better chaining of functions.
Break your code apart so that the two AJAX calls are in separate functions, and have both those functions return the result of their $.ajax call. You can then use:
func1().then(func2).then(...);
func2 will be passed the result of the first AJAX call, and then the result of that will be passed to whatever function is in the final then.
In your case you can also put the call to parseODataResultTest in the chain and then the final function will (eventually) be called with the required data, i.e.:
getEnt_PodType().then(getProjects).then(parseODataResultTest).then(function(projects) {
// use projects here, and _only_ here because it won't
// be in scope or defined anywhere else
...
});

javascript and order of execution of functions

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
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.
$.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.
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.

Javascript callback functions with ajax

I am writing a generic function that will be reused in multiple places in my script.
The function uses ajax (using jQuery library) so I want to somehow pass in a function (or lines of code) into this function to execute when ajax is complete.
I believe this needs to be a callback function, but after reading through a few callback answers I'm still a bit confused about how I would implement in my case.
My current function is:
function getNewENumber(parentENumber){
$.ajax({
type: "POST",
url: "get_new_e_number.php",
data: {project_number: projectNumber, parent_number: parentENumber},
success: function(returnValue){
console.log(returnValue);
return returnValue; //with return value excecute code
},
error: function(request,error) {
alert('An error occurred attempting to get new e-number');
// console.log(request, error);
}
});
}
With this function I want to be able to do something in the same way other jQuery functions work ie;
var parentENumber = E1-3;
getNewENumber(parentENumber, function(){
alert(//the number that is returned by getNewENumber);
});
Just give getNewENumber another parameter for the function, then use that as the callback.
// receive a function -----------------v
function getNewENumber( parentENumber, cb_func ){
$.ajax({
type: "POST",
url: "get_new_e_number.php",
data: {project_number: projectNumber, parent_number: parentENumber},
// ------v-------use it as the callback function
success: cb_func,
error: function(request,error) {
alert('An error occurred attempting to get new e-number');
// console.log(request, error);
}
});
}
var parentENumber = E1-3;
getNewENumber(parentENumber, function( returnValue ){
alert( returnValue );
});
#patrick dw's anwser is correct. But if you want to keep calling the console.log (or any other actions) always, no matter what the caller code function does, then you can add the callback (your new parameter) inside the success function you already have:
function getNewENumber(parentENumber, cb_func /* <--new param is here*/){
$.ajax({
type: "POST",
url: "get_new_e_number.php",
data: {project_number: projectNumber, parent_number: parentENumber},
success: function(returnValue){
console.log(returnValue);
cb_func(returnValue); // cb_func is called when returnValue is ready.
},
error: function(request,error) {
alert('An error occurred attempting to get new e-number');
// console.log(request, error);
}
});
}
And the calling code remains the same as yours except that the function will receive the returnValue by parameter:
var parentENumber = E1-3;
getNewENumber(parentENumber, function(val /* <--new param is here*/){
alert(val);
});
This would be better done with jQuery's Deferred Objects. Have your AJAX call return the jqXHR object.
function getNewENumber(parentENumber) {
return $.ajax( { ... } );
}
getNewENumber(E1 - 3).then(success_callback, error_callback);
If you want to keep the error callback within that function you can register that there instead:
function getNewENumber(parentENumber) {
var jqXHR = $.ajax( { ... } );
jqXHR.fail( ... );
return jqXHR;
}
getNewENumber(E1 - 3).done(success_callback);

Categories

Resources