I have a strange (probably not for some I would wager) problem, I have a JavaScript method to call all of my ajax calls, please see below.
function ajaxCall(url, params) {
if (params === null) {
$.ajax({
type: 'POST',
url: url,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).success(function(response) {
return response;
}).error(function(response) {
return response;
});
} else {
var data = JSON.stringify(params);
$.ajax({
type: 'POST',
url: url,
data: data,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).success(function(response) {
return response;
}).error(function(response) {
return response;
});
}
}
when I call this method I get the appropriate response from the AJAX call and all looks rosy, until I return the response the call is returned undefined?
for completeness I will include my call code.
var call = ajaxCall(someUrl, someParams);
just to clarify and make sure my ramblings are understood call would be undefined in the above example?
you can't do that because the ajax call is async,
$.ajax returns a Deferred Object and you can work with it to get what you need
read on it here
the ajax call is async by nature and dosent return anything. so when you do something like this
var call = ajaxCall(someUrl, someParams);
then a request is sent to the server and next lines begins to execute. without putting the value in the call variable;
also code like this
.success(function(response) {
return response;
would do nothing as .success() takes a function or rather a callback to execute when the response is successfull so if u return something in this and put the async flag in the $.ajax() options to true. then also nothing/undefined will be returned.
Related
I'm trying to send data off with data from multiple other Ajax requests. The issues comes when sendDataOffAjax() is called, no actual data was sent, because it fires off before any of the other functions have a change to add data. I could easily fix this by just using asyn: false everywhere, but from what I read, that's bad practice.
Here is my code:
let requests = [];
$.ajax({
url: someUrl,
method: 'GET',
dataType: 'json',
complete: function (data) {
if (data.exists) {
if (condition) {
requests.push(anotherAjax());
}
if (condition) {
requests.push(someDifferentAjax());
}
}
requests.push(alwaysRunAjax());
}
}).done(function () {
$.when.apply($, requests).done(function () {
sendDataOffAjax();
});
});
Heres what anotherAjax() looks like (All the other Ajax requests also look like this):
function anotherAjax() {
return $.ajax({
url: someUrl,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
method: 'GET',
dataType: 'json',
complete: function (data) {
if (data.exists) {
toSendData.data['NEW_DATA'] = {
'data': data.responseJSON
}
}
//send complete signal?
}
})
}
How could I make it wait until all the data is added through the other Ajax requests, then launch sendDataOffAjax().
The log looks like this:
Data sent
anotherAjax Data added
alwaysRunAjax Data added
someDifferentAjax Data added
When it comes to ajax requests, .complete(), according to jQuery's docs, runs only after the success or error callback is run and .done() is the same as calling .success(). So with this in mind you can see why the code in your done callback is running first. You should be able to switch the code from your complete callback to your done callback and vice-versa to get the desired effect.
So Try:
let requests = [];
$.ajax({
url: someUrl,
method: 'GET',
dataType: 'json',
complete: function () {
$.when.apply($, requests).done(function () {
sendDataOffAjax();
});
}
}).done(function (data) {
if (data) {
if (condition) {
requests.push(anotherAjax());
}
if (condition) {
requests.push(someDifferentAjax());
}
}
requests.push(alwaysRunAjax());
});
Now, as long as all of your ajax functions you are calling here return deferred objects your requests array should be filled and $.when() should wait until all the deferred objects resolve.
No this isn't possible without async:false.
The reason it doesn't count as a good thing to use is becuase it is against the idea of a Ajax which is Asynchronous.
async:false baisiclly "lock" your application to the user until your request is done and when you put it on too much ajax calls in the same time it will make your apllication seems very very slow.
In your case you it will be fine if you'll use async:false on the 2 functions as long as they don't take long to execute.
I have a controller that returns the following line:
Json(null, JsonRequestBehavior.AllowGet);
This method in the controller is executed by an Ajax request like this:
return new Promise (function(resolve, reject)
{ $.ajax({
type: 'POST',
url: GL_ROOT + "AccountingCompany/DeleteAccountingCompany",
data: JSON.stringify({ id: id }),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (deleteResult) {
resolve(deleteResult);
}
});
});
When I set a break-point in the success part, it never gets there. But if I changed the result from the controller to Json(-1, JsonRequestBehavior.AllowGet); it gets to the break-point in the success part of the Ajax request.
Can somebody know the reason why I can not reach the break-point?.
There might be parsing issues in client side when trying to resolve the out come of Json(null), which translates to an empty string.
Try using Json(new {}, JsonRequestBehavior.AllowGet) instead.
Hope it helps.
I've got a small javascript function that's only purpose is to call a script to get some data from the database so it can be used by other functions on the client side.
I'm using a jQuery call to get the data but for me to pass the object out of the success functions scope I need to turn asynchronous off which raises a deprecation warning.
My function works as intended currently but I'd like to use a method that isn't deprecated. Here is my function:
function getData(ID) {
var Data = {};
$.ajax({
url: 'script',
method: 'POST',
dataType: 'json',
async: false,
data: {action: 'get', id: ID },
success: function(response) {
Data = response;
})
});
return Data;
}
I've changed the variable names for privacy reasons so apologies if they're vague.
Also why is synchronous calls considered harmful to the end users experience?
As AJAX call is asynchronous, you will always get blank object ({}) in response.
There are 2 approach.
You can do async:false
To get response returned in AJAX call try like below code. Which wait for response from server.
function getData(ID) {
return $.ajax({
url: 'script',
method: 'POST',
dataType: 'json',
//async: true, //default async call
data: {action: 'get', id: ID },
success: function(response) {
//Data = response;
})
});
}
$.when(getData(YOUR_ID)).done(function(response){
//access response data here
});
I have an ajax call that might take a bit to complete. I don't want to use async:false because I want it to stay non blocking code. So I decided to use Q. The problem is I don't understand how ca I extract the json that came back from Q.when($.ajax...). I'm new to Q.
In this example I would like the variable to hold the json that came back from the server:
var res = Q.when($.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
}));
return res;
With asynchronous calls you can't just assign the result to a variable, because that result won't exist until sometime in the future. Q.when does not return the result, it returns a promise object that will eventually resolve with a result.
If there is only ever one thing you want to do with the JSON you could just inline a .then call to get the result.
Q($.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
})).then(function (res) {
// res now contains the JSON
});
However the real power of promises comes with the fact that you can pass them around and use them later.
function getMembersList() {
return Q($.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
}));
}
var membersList = getMembersList();
membersList.then(function (res) {
// once the AJAX call completes this will
// run. Inside this function res contains the JSON
return res; // pass res to the next chained .then()
}).then(function (res) {
// you could chain another then handler here
});
// do some other stuff
membersList.then(function (res) {
// you could also add another then handler later too
// even long after the AJAX request resolved and this
// will be called immediately since the promise has already
// resolved and receive the JSON just like the other
// then handlers.
});
You don't need to use Q if you don't have other reasons for using it, since version 1.5 jQuery returns a deferred object from AJAX calls. A Deferred is similar to a promise. Q does offer more power and jQuery's promises/deferreds don't exactly implement the Promises/A standard, potentially causing problems with error handling. For something simple like an AJAX call jQuery promises are usually good enough if you are already using jQuery anyway.
var membersList = $.ajax({
type: "POST",
url: "GetData.asmx/GetMembersList",
contentType: "application/json; charset=utf-8",
dataType: "json"
});
membersList.then(function (res) {
// res now contains the JSON
});
Here are some examples from the q documentation about using with jQuery ajax.
return Q(jQuery.ajax({
url: "foobar.html",
type: "GET"
})).then(function (data) {
// on success
}, function (xhr) {
// on failure
});
// Similar to jQuery's "complete" callback: return "xhr" regardless of success or failure
return Q.promise(function (resolve) {
jQuery.ajax({
url: "foobar.html",
type: "GET"
}).then(function (data, textStatus, jqXHR) {
delete jqXHR.then; // treat xhr as a non-promise
resolve(jqXHR);
}, function (jqXHR, textStatus, errorThrown) {
delete jqXHR.then; // treat xhr as a non-promise
resolve(jqXHR);
});
});
https://github.com/kriskowal/q/wiki/Coming-from-jQuery
Hope that helps.
I am trying to implement Repository pattern in JavaScript. I have ViewModel which i want to initialize with the data when i call Initialize method on it. Everything seems to be falling in places except that i am not able to return the data from my AJAX call. I can see that data is coming back from the ajax call but when i trying to capture the data in SomeViewModel's done function, it is null.
Can someone please point me out where i am going wrong here?
P.S: Please notice that i am not making Async call so the call chain is properly maintained.
This is how my Repository looks like:
function SomeRepository(){
this.LoadSomeData = function loadData()
{
$.ajax({
type: "POST",
url: "someUrl",
cache: true,
async: false,
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
//success: handleHtml,
success: function(data) {
alert('data received');
return data;
},
error: ajaxFailed
});
function ajaxFailed(xmlRequest) {
alert(xmlRequest.status + ' \n\r ' +
xmlRequest.statusText + '\n\r' +
xmlRequest.responseText);
}
}
};
This is how my ViewModel looks like:
function SomeViewModel(repository){
var self = this;
var def = $.Deferred();
this.initialize = function () {
var def = $.Deferred();
$.when(repository.LoadSomeData())
.done(function (data) {
def.resolve();
});
return def;
};
}
This is how i am calling from an aspx page:
var viewModel = new SomeViewModel(new SomeRepository());
viewModel.initialize().done(alert('viewmodel initialized'));
alert(viewModel.someProperty);
I have used successfully an auxiliar variable to put the ajax result, when ajax call is inside a function (only works if ajax is async=false) and i need the function does return the ajax result. I don't know if this is the best solution.
function ajaxFunction(){
var result='';
$.ajax({
type: "POST",
url: "someUrl",
cache: true,
async: false,
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
//success: handleHtml,
success: function(data) {
alert('data received');
result=data;
},
error: ajaxFailed
});
return result;
}
Doesn't matter that it's synchronous (though it really shouldn't be). Returning a value from inside the ajax callback will not cause the value to be returned from the containing function.
Using asynchronous ajax is generally a much better idea anyway, but that will force you to create an API that allows its clients to pass in handlers to be called when the ajax request completes. To do that, you'd give your "LoadSomeData" function a parameter. A caller would pass in a function, and your ajax "success" handler would pass on the results (or some transformation of the results; depends on what it is that you're doing) to that callback. It's the same idea as the callbacks used in the ajax call itself.