Deferred jQuery AJAX request does not run done() callback function - javascript

I have setup a simple demo using jQuery Deferred object with AJAX request to simulate how my app is doing it.
My issue is, ever since I switched over from the older non-deferred method, I cannot get a success callback.
Only the fail() callback is called. Can someone help me to get a successful callback? I don't see where it is going wrong? Appreciate any help
My demo is here http://jsfiddle.net/jasondavis/y645yp4g/4/
My old AJAX call was like this...
var ajax = $.ajax({
type: 'POST',
async: false,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: '/gettask',
data: {
action: 'load-task-record',
task_id: taskId
},
success: function(data) {
// my success functionality here
}
});
New AJAX call using Deferred object...
// Call function that execute AJAX request and returns it
var ajaxRequest = ajaxLoadTaskData();
ajaxRequest.done(function(response) {
if( response.success ) {
alert('AJAX request success');
}else{
// output the contents of response.errors
}
}).fail(function(response) {
// AJAX request failed
console.log('response', response);
alert('AJAX request failed');
}).always(function(response) {
});
// Run AJAX request and return Promise()
function ajaxLoadTaskData() {
return $.ajax({
type: 'POST',
async: false,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
url: '/gettask',
data: {
action: 'load-task-record',
task_id: '1',
},
});
}
Mock AJAX response for AJAX request to /gettask
// Mock AJAX response for AJAX request to /gettask
$.mockjax({
url: '/gettask',
contentType: 'text/json',
responseTime: 100,
response: function(settings) {
console.log('mockJax GET to /gettask :');
//console.log(settings);
if (settings.data.value == 'err') {
this.status = 500;
this.responseText = 'Validation error!';
} else {
var taskrecord = { 'name1': 'bar' };
this.responseText = taskrecord;
}
},
});

/gettask doesn't exists in that jsFiddle environment. Use console.log(settings) to see the entire content of the response. You will se that the status is 404.

Related

Getting Data from Ajax request displayed

I've already read this article How do I return the response from an asynchronous call? However I couldn't come up with a solution.
I'm doing an ajax request
function getdata(url)
{
console.log('Started');
jQuery.ajax({
type: "GET",
url: "http://myserver.com/myscript.php",
dataType: "json",
error: function (xhr) {
console.log('Error',xhr.status);
},
success: function (response) {
console.log('Success',response);
}
});
}
And Console displays everything fine but when I say
var chinese = getdata();
to get the data. I keep getting:
Uncaught TypeError: Cannot read property 'length' of undefined error for this line
var text = chinese[Math.floor(Math.random()*chinese.length)];
Can anybody help me here?
The problem is that you are using an asynchronous method expecting a synchronous result.
Therefore you should use the code in the result of the asynchronous call like the following:
function getdata(url) {
console.log('Started');
jQuery.ajax({
type: 'GET',
url: url,
dataType: 'json',
error: function(xhr) {
console.log('Error', xhr.status);
},
success: function(chinese) {
var text = chinese[Math.floor(Math.random()*chinese.length)];
// Do something else with text
}
});
}
getData('http://myserver.com/myscript.php');
I hope it helps :)
The error you get is because of the asynchronous nature of the call. I suggest you to assign the value after you get the success response from the API like below.
var chinese = getdata();
Then the function getdata() will be like
function getdata(url)
{
console.log('Started');
jQuery.ajax({
type: "GET",
url: "http://myserver.com/myscript.php",
dataType: "json",
error: function (xhr) {
console.log('Error',xhr.status);
},
success: function (response) {
initChinese(response.data);
}
});
}
And create a function initChinese() like
var text;
function initChinese(chinese){
text = chinese[Math.floor(Math.random()*chinese.length)];
}
You can also declare the text variable in global scope and then assign the value to text variable inside the success function without having to create a new function initChinese.
The problem is your getdata function does not return anything. In your getdata function you're doing a ajax request, which is an asynchronous request. So the data you're requesting won't, and can't be returned with your getdata function.
But you will have the requested data in your success function:
function getdata(url)
{
console.log('Started');
jQuery.ajax({
type: "GET",
url: "http://myserver.com/myscript.php",
dataType: "json",
error: function (xhr) {
console.log('Error',xhr.status);
},
success: function (response) {
console.log('Success',response);
var text = response[Math.floor(Math.random()*response.length)];
}
});
}
As I'm not able to test your code, you've to debug the rest on your own. But the response variable will be most likely your "chinese" variable.
You could try using callbacks or you could look at Promises.
The idea with callbacks is that you pass a function that is run after the ajax request is finished. That callback can accept a parameter, in this case the response.
Using callbacks:
function getData(url, successCallback, errorCallback) {
console.log('Started');
jQuery.ajax({
type: "GET",
url: url,
dataType: "json",
error: function(xhr) {
errorCallback(xhr.status);
},
success: function(response) {
successCallback(response);
}
});
}
var chinese;
getData("http://myserver.com/myscript.php", function(response) {
chinese = response; // you can assign the response to the variable here.
}, function(statusCode) {
console.error(statusCode);
});
Using Promises (< IE11 doesn't support this):
function getData(url) {
return new Promise(function(resolve, reject) {
console.log('Started');
jQuery.ajax({
type: "GET",
url: url,
dataType: "json",
error: function(xhr) {
reject(xhr.status);
},
success: function(response) {
resolve(response);
}
});
});
}
var chinese;
getData("http://myserver.com/myscript.php").then(function(response) {
chinese = response;
console.log(chinese);
}, function(statusCode) {
console.error(statusCode);
});

How to force $ajax to wait for data and assign these to a variable?

I have trouble async disable ajax. I have the following code:
function GetDataFromUninorte() {
link="http://www.uninorte.edu.co/documents/71051/11558879/ExampleData.csv/0e3c22b1-0ec4-490d-86a2-d4bc4f512030";
var result=
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: function(response) {
console.log("Inside: " + response);
}
}).responseText;
console.log("Outside: "+result);
return result;
}
And I get the following result:
"Outside" always runs first
As you can see, "Outside" always runs first and the result is undefined and can not process data.
I have already tried
When ... Then
Async = false
passing data as parameters I / O function
and other things, but nothing
:/
... Beforehand thank you very much
(I am not a native english speaker, I apologize if I do not write well)
[Solved]
Maybe is not the best form, but in the "success:" statement I call a function that receive the ajax response and trigger the rest of the process, in this way I not need store the in a variable and the asynchrony not affect me.
Use can use callbacks, you can read more here
function GetDataFromUninorte(successCallback, errorCallback) {
link="http://www.uninorte.edu.co/documents/...";
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: successCallback,
error: errorCallback
});
}
function mySuccessCallback(successResponse) {
console.log('callback:success', successResponse);
}
function myErrorCallback(successResponse) {
console.log('callback:success', successResponse);
}
GetDataFromUninorte(mySuccessCallback, myErrorCallback);
Or you can use promises (bad support in IE browsers)
function GetDataFromUninorte() {
return new Promise(function(resolve, reject) {
link="http://www.uninorte.edu.co/documents/...";
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: resolve,
error: reject
});
});
}
GetDataFromUninorte()
.then(function(successResponse){
console.log('promise:success', successResponse);
}, function(errorResponse){
console.log('promise:error', errorResponse);
});
AJAX being asynchronous by nature, you need to pass callback, which will be called when the ajax response is received. You may then access responseText from the xhr object.
You can also you jQuery Deferred and promise to get around your problem like below:
function GetDataFromUninorte() {
var defObject = $.Deferred(); // create a deferred object.
link="http://www.uninorte.edu.co/documents/71051/11558879/ExampleData.csv/0e3c22b1-0ec4-490d-86a2-d4bc4f512030";
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
async: false,
dataType: 'json',
success: function(response) {
console.log("Inside: " + response);
defObject.resolve(response); //resolve promise and pass the response.
}
});
return defObject.promise(); // object returns promise immediately.
}
and then:
var result = GetDataFromUninorte();
$.when(result).done(function(response){
// access responseText here...
console.log(response.responseText);
});
You should avoid making AJAX synchronous by setting async:false as that will block further interactions on the User Interface.
Use this:
function GetDataFromUninorte() {
link="http://www.uninorte.edu.co/documents/71051/11558879/ExampleData.csv/0e3c22b1-0ec4-490d-86a2-d4bc4f512030";
var result=
$.ajax({
url: 'http://whateverorigin.org/get?url=' + link +"&callback=?" ,
type: 'GET',
**timeout: 2000,**
async: false,
dataType: 'json',
success: function(response) {
console.log("Inside: " + response);
}
}).responseText;
console.log("Outside: "+result);
return result;
}

Working with Ajax Promises / Deferred

I am trying to get an Ajax promise using the code below. Because my function makes another ajax call before initiating the actual one , for getting the authKey, The promise (that should have been returned) from the actual call is null, & I cannot use .then() on it because I think I am not getting anything in return from it. I am not sure why.
What am I doing wrong here? Is there any other way to go about this. I call getAjaxPromise() like mentioned below but get null in return:
getAjaxPromise(myUrl, true, myType, myContentType, mySuccessFunction, myFailureFunction,
myData, true)
.then(function(data) //.then() gives undefined-null error
{
//Do something with the data returned form actual Ajax call.
});
self.getAjaxPromise = function(url, async, type, contentType, successCallback,
errorCallback, data, isSecureCall)
{
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
tokenPromise.then(function(tokenData) { //This then runs fine
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
});
});
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
}
};
you forgot to return the getTokenPromiseFromServer
if isSecureCall is true your function return null
self.getAjaxPromise = function(url, async, type, contentType, successCallback,
errorCallback, data, isSecureCall)
{
if (isSecureCall) {
return getTokenPromiseFromServer().then(function(tokenData) {
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
});
});
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
}
};
You had forgot to return the promise inside the if statement, you are return it only on else, the fixed code below:
self.getAjaxPromise = function(url, async, type, contentType, successCallback,
errorCallback, data, isSecureCall) {
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
tokenPromise.then(function(tokenData) {
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", tokenData.key);
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback, //Success callback runs fine, then() does not
error: errorCallback, //Error callback runs fine, then() does not
data: JSON.stringify(data)
});
});
return tokenPromise;
} else { //Just one ajax call
return $.ajax({
beforeSend: function(request) {
request.setRequestHeader("authKey", "anonymous");
},
url: url,
async: async,
type: type,
contentType: contentType,
success: successCallback,
error: errorCallback,
data: JSON.stringify(data)
});
});
}
};
You forgot to return tokenPromise
you must return it from first if
if (isSecureCall) {
var tokenPromise = getTokenPromiseFromServer(); //Another Ajax call to get latest token from service
// ...
return tokenPromise;
}

.done() jquery not working

Im using the below code for a ajax call
var getRequest = $.ajax({
type: 'GET',
url: Url,
async: false,
dataType: "text",
complete: function () {
$('#loading').hide();
}
});
the request is getting complete and data is also withdrawn after the data is recieved the following:
getRequest.done(function (dataDb) {
if (dataDb) {
alert('dataDb: ' + dataDb);
}
});
getRequest.fail(function (jqXHR, textStatus, error) {
alert('data error within getUsersRequest ' + textStatus + ' : ' + error);
});
I'm recieving a error that getRequest.done(function(dataDb) or getRequest.fail(function(jqXHR, textStatus, error) is not a function.
It is because your JQuery version is too old.
You can use success if you are not willing to upgrade the latest version of JQuery.
success: function(dataDb) {
}
success only fires if the AJAX call is successful from back end, i.e. it returns a HTTP 200 status as response. if any error fires if it fails and complete when the request finishes, regardless of success.
In jQuery 1.8 on the jqXHR object (returned by $.ajax) success is being replaced with the done, error with fail and complete with always.
However you should still be able to initialise the AJAX request with the current syntax. So these do similar things:
// set success action before making the request
$.ajax({
url: '...',
success: function(){
alert('AJAX successful');
}
});
// set success action just after starting the request
var jqxhr = $.ajax( "..." )
.done(function() { alert("success"); });
Last: you need to use .success rather then using .done
You can try using .success.
var getRequest = $.ajax({
type : 'GET',
url : Url,
async: false,
dataType: "text",
complete: function(){
$('#loading').hide();
}
}).success(function(dataDb){
if(dataDb) {
alert('dataDb: '+ dataDb);
}
});

problems executing a jquery ajax call within a function

I would like to put an ajax call within a function since I use it repeatedly in multiple locations. I want a manipulated version of the response returned. Here's what I'm trying to do (greatly simplified).
a = getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
return response;
});
}
What's happening, however, is that the append function is running before "a" has been defined in the getAjax function. Any thoughts?
AJAX is asynchronous. This means that the code in the success handler is delayed until the request is successful, while the rest of the code continues as normal. You need to put the relevant code in the AJAX success handler:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
$(document.body).append('<div>'+response+'</div>');
});
}
Note that I have also optimised your body selector by using the native Javascript document.body rather than using the standard tag selector.
Edit Callback version
function getAjax(callback) {
$.ajax({
type: 'GET',
url: 'someURL',
success: callback
});
}
You can now do the code inline using a callback function:
getAjax(function(response) {
$(document.body).append('<div>'+response+'</div>');
});
or
getAjax(function(response) {
alert(response);
});
or whatever.
The code inside the anonymous function call will be processed when the AJAX request is complete.
There are two ways to taggle this. one is to use the success callback:
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
the other is to set async to false http://api.jquery.com/jQuery.ajax/:
var a;
getAjax();
$('body').append('<div>'+a+'</div>');
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
async: false,
success: function(response) {
a = response;
});
}
Important note on non async:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Why don't you return the response to another function in the success callback. This should handle your need for different responses:
getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
AppendResponse(response);
});
}
function AppendResponse(response) {
$('body').append('<div>'+response+'</div>');
}
One suggestion I have is to pass a trigger to the command you want to run into the AJAX function so that it will run after AJAX has received a response-
a = getAjax();
function getAjax() {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
inputText(response);
});
}
inputText(someText) {
$(document.body).append('<div>'+ someText +'</div>');
}
That way you can create if statements / other alternatives to continue to use the same AJAX command for different results
You can give a handler to the function getAjax(), but if the user needs the information for the next decision then why not wait using async: false?
function getAjax(handler) {
$.ajax({
type: "GET",
url: 'someURL',
success: function(response) {
handler(response);
});
};
function callGetAjax(response) {
if(response === undefined) {
getAjax(callGetAjax);
} else {
$('body').append('<div>'+response+'</div>');
}
}

Categories

Resources