Ajax call does not happen synchronously - javascript

I make a call with Ajax to an IP with some arguments. Before the call that matters (lets call that "call 2") can be executed, it has to make an Ajax call to get a sessionId (and lets call that "call 1"). The sessionId is necessary to make any call to the IP and have it do something with the arguments.
But when I have the function below each other, it first does "call 2" and after that "call 1". Classic async behavior but since in the Ajax call I say async: false, I don't really understand why it isn't doing what I say it has to do.
Complete Ajax Call "call 1":
Url = "_ip_?action=getsessionid";
$.ajax({
url: Url,
type: "Post",
dataType: "jsonp",
async: false,
success: function( json ){
var j = $.parseJSON(json);
var sessionid = j['sessionId'];
},
error: function( errorThrown ) {
console.log(errorThrown);
}
});
And Ajax call "call 2":
Url = "_ip_?action=action&sessionId=" + sessionid;
$.ajax({
url: Url,
type: "Post",
dataType: "jsonp",
async: false,
success: function( json ){
var j = JSON.parse(json);
//do something with j
},
error: function( errorThrown ) {
console.log(errorThrown);
}
});
Just assume variable sessionid does give the sessionid to "call 2".
As you can see, I get an json string returned.
What I did now is that the next Ajax call only gets initialized and executed when the first Ajax call was successfully executed. This seems a workaround to me and not a proper way to do what I try to accomplish.

from JQuery.ajax documentaton:
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().
With that. My solution is to make the next ajax request inside the success function. The JQuery documentation explains this more. http://api.jquery.com/jquery.ajax/

Define var sessionid as global variable and assign the value to the same in ajax call1 and then access this value in call2.
var sessionid='';
Url = "_ip_?action=getsessionid";
$.ajax({
url: Url,
type: "Post",
dataType: "jsonp",
async: false,
success: function( json ){
var j = $.parseJSON(json);
sessionid = j['sessionId'];
},
error: function( errorThrown ) {
console.log(errorThrown);
}
});

Related

jQuery multiple ajax calls inside for loop logging same responses

My code is something like this:
for (var i = 0; i < stf_file_names.length; i++) {
var temp_file_name = stf_file_names[i];
$.ajax({
type: "POST",
url: "php_scripts/some_script.php",
data: {
stf_file_name: temp_file_name
},
timeout: 600000,
success: function (response) {
console.log("SUCCESS : ", response);
//pausecomp(2000);
}
});
}
Here, some_script.php updates a database in the backend and echo's the primary key of the updated row, which is a number. But when I'm logging using the success function, I can see that it is logging only the primary key echoed by the last ajax call multiple times.
But if I use some kind of sleep function, which is pausecomp() in this case, it prints different the primary keys echoed.
I have looked at multiple stackoverflow questions regarding this and have not been to solve it.
async: false will do the job
$.ajax({
type: "POST",
async: false,
url: "php_scripts/some_script.php",
data:
However, this is not recommended, Better to make a loop by calling a function recursively from success.
Here is the example.
i=0;
function loop_stf_file_names(i){
var temp_file_name = stf_file_names[i];
$.ajax({
type: "POST",
url: "php_scripts/some_script.php",
async: false,
data: {
stf_file_name: temp_file_name
},
timeout: 600000,
success: function (response) {
console.log("SUCCESS : ", response);
if( i < stf_file_names.length ){
loop_stf_file_names( ++i );
}
}
});
}
$.ajax() is a async function.
By looping over ajax you are most probably sending the same data in all requests, due to which you are receiving same key for all requests.
Just sure , you send the next request when you have received the response from first request.

What's a non-deprecated way of doing a synchronous ajax call using jQuery?

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
});

Syntax Error after JSONP request

I'm trying to fetch the data of a JSONP, but it returns a Syntax error when the function is called. I'm really new to this topic and don't understand why. Probably because I didn't understand everything of JSONP requests. It would be nice if someone could help me out.
Executed code:
$.ajax({
url: "https://backpack.tf/api/IGetMarketPrices/v1?format=json&callback=JSONP&key=XXX&appid=730",
dataType: "jsonp",
data: {format: "json"},
type: "GET",
jsonp: "response",
jsonpCallback: "response",
success: function( response ) {
console.log( response ); // server response
}
});
(I had to censor my API key.)
Error: Uncaught SyntaxError: Unexpected token :
The response is:
{"response":{"success":1,"current_time":1486000891,"items":{"AK-47 | Aquamarine Revenge (Battle-Scarred)":{"last_updated":1485997229,"quantity":80,"value":1092},...
The first : is underlined by Chrome.
Here is the API documentation.
From trial and error - impressive as I have no API key
$.ajax({
url: "https://backpack.tf/api/IGetMarketPrices/v1?format=jsonp&key=XXX&appid=730",
dataType: "jsonp",
type: "GET",
success: function( response ) {
console.log( response ); // server response
}
});
or
$.ajax({
url: "https://backpack.tf/api/IGetMarketPrices/v1",
dataType: "jsonp",
type: "GET",
data: {
format: 'jsonp',
key: 'XXX',
appid: 730
},
success: function( response ) {
console.log( response ); // server response
}
});
To explain... jQuery automatically adds a query parameter called callback on jsonp requests... as the API states that you need to define the callback name in a parameter called callback, you can let jQuery use the default value of callback
Then, jQuery creates a function with a long random name, and sets the value of the callback parameter to that function - so you don't have to worry about the jsonp or jsonpCallback parameters - defaults are good
I must be missing something basic, because this should work!

Setting Variable During Callback

The following jQuery code attempts to store a client's IP address in a global variable during the callback for an ajax GET request.
Code
var userip = null;
$.ajax({
url: "http://ipinfo.io",
type: 'get',
dataType: 'jsonp',
async: false,
success: function(data) {
userip = data.ip;
console.log(userip); // prints unique ip address
}
}).done(console.log(userip)); // prints null
Knowing that GET requests are usually executed asynchronously (but requiring otherwise), I have marked async: false in the JSON spec. For added measure, I call done() to ensure the request has finished before continuing.
Nevertheless, printing userip returns null after the GET request but prints the unique client IP during the ajax success callback.
Any explanation would be greatly appreciated. Thanks in advance.
.done() expects a callback. Try swapping out
console.log(userip)
with
function() { console.log(userip); }
what you're doing is making the console.log(userip) execute immediately, and not after the request is completed. Which is why userip gets stored properly in the success handler. Think of done as what to do once the request is completed. It needs to execute an action (function). You're passing a statement (console.log(userip)) which actually returns undefined. So done doesn't do anything.
try this instead
}).done(function() {
console.log(userip);
});
Try this
var userip = null;
$.ajax({
url: "http://ipinfo.io",
type: 'get',
dataType: 'jsonp',
async: false,
success: function (data) {
userip = data.ip;
console.log(userip); // prints unique ip address
},
complete: function () {
console.log(userip); // prints unique ip address
}
});

ajax call doesnt return the data from external JS file

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.

Categories

Resources