$.ajax wait for completion without hanging the UI - javascript

Let's say for example, I have the following javascript function that returns a boolean:
function CallWebServiceToUpdateSessionUser(target, user)
{
var dataText = { "jsonUser": JSON.stringify(user) };
$.ajax({
type: "POST",
url: target,
data: JSON.stringify(dataText),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response)
{
return true;
},
failure: function (msg)
{
return false;
}
});
}
and the target function on the server that is being called could take up to... 15 seconds to respond.
How do I guarantee that this function will not exit until after the server call has been completed? Or, how can I guarantee that who ever is calling this function will get a true/false and not an undefined?
NOTE:
I've seen people use async: false but that hangs the UI which I do not want.

See http://api.jquery.com/jQuery.ajax/. You need to do an AJAX request with async: true to your parameters. You will then need to edit your code so the code that executes after a successful request is inside the successful block.

Related

How to pass a variable from ajax to nested ajax

I'm sending ajax call and getting an answer that I need from the first ajax then I want to pass my result to my nested ajax, my var (result) is null in the nested ajax/settimeout fun, can I pass it ? Am I missing something ?
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
contentType:'json' ,
dataType:'text',
success: function (result) {
alert(result);**-> is fine - not null**.
// a or result is null when I hit the getCurrentDoc- function althought I get the data I need from getCustomerGuidId function
var a = result;-> tried to pass it to a new var..IDK.. I
thought it will help... it didn't.
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,-> here it's null
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});
You can try something like this will help to pass value to nested ajax call
function test(){
var myText = 'Hello all !!';
$.get({
//used the jsonplaceholder url for testing
'url':'https://jsonplaceholder.typicode.com/posts/1',
'method':'GET',
success: function (data) {
//updating value of myText
myText = 'welcome';
$.post({
'url':'https://jsonplaceholder.typicode.com/posts',
'method':'POST',
//data.title is the return value from get request to the post request
'data':{'title':data.title},
'success':function (data) {
alert(data.title +'\n' + myText);//your code here ...
}
});
}
});
}
An old question and you've likely moved on, but there's still no accepted answer.
Your setTimeout takes an anonymous function, so you are losing your binding; if you have to use a Timeout for some reason, you need to add .bind(this) to your setTimeout call (see below)
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
contentType:'text',
data: a,
success: function (data) {
}
});
}.bind(this), 2000);
At a guess you're using a Timeout because you want to ensure that your promise (i.e. the first ajax call) is resolving prior to making the nested call.
If that's your intention, you can actually scrap setTimeout completely as you have the nested call in the first ajax success call, which only runs once the promise has been resolved (providing there isn't an error; if so, jQuery would call error rather than success)
Removing setTimeout means you won't lose your binding, and a should still be result (hopefully a is an object, otherwise your second call is also going to experience issues...)
Lastly, after overcoming the binding issue you wouldn't need var a = result; you should be able to pass result directly to your nested ajax call.
Good luck!
In the nested ajax you send a as a param name, not as a param value.
So you can try the following (change param to actual param name which your server expects):
$.ajax({
url: '#Url.Action("getCustomerGuidId", "Document")',
type: 'POST',
cache: false,
data: { "classNum": currentclassNum},
dataType:'text',
success: function (result) {
setTimeout(function () {
$.ajax({
type: "GET",
url: '#Url.Action("getCurrentDoc", "Document")',
data: {param: result},
success: function (data) {
}
});
}, 2000);
},
error: function (result) {
alert("fail " + result);
}
});

How to run another JS method from longPolling?

How in method with longPolling:
function getNewMessagesLong() {
pollingFishingStarts();
$request = $.ajax({
type: 'POST',
url: "listenMessageLong",
data: lastIncomingMessageLongJson,
dataType: 'json',
success: function(data) {
}, complete: getNewMessagesLong})
}
on complete to run another method?:
function pollingFishingEnds() {
document.getElementById("fishing-end").src = "resources/img/fishing-end.png";
document.getElementById("fishing-start").src = "resources/img/fishing-start-empty.png";
}
With the example you posted, you could simply do something like this, adding an anonymous function that calls your "ends" method AND restarts your polling method:
function getNewMessagesLong() {
pollingFishingStarts();
$request = $.ajax({
type: 'POST',
url: "listenMessageLong",
data: lastIncomingMessageLongJson,
dataType: 'json',
success: function(data) {
},
complete: function() {
getNewMessagesLong();
pollingFishingEnds();
}
});
}
You could also change up to a window.setInterval() long-polling paradigm that would allow you to use your complete option to set your actual end method, rather than hijacking it for long-polling.
I'm assuming here that you want to call the "end" state code after the first round completion. Otherwise, there's literally no end to your polling, unless you have some server message to terminate, in which case you need to post that code for additional information.

Two Ajax onclick events

So I have had to modify some old existing code and add another ajax event to onclick
so that it has onclick="function1(); function2();"
This was working fine on our testing environment as it is a slow VM but on our live environment it causes some issues as function1() has to finished updating some records before function2() gets called.
Is there a good way to solve this without modifying the js for function2() as this the existing code which is called by other events.
Thanks
Call function2 upon returning from function1:
function function1() {
$.ajax({
type: "POST",
url: "urlGoesHere",
data: " ",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
//call function2
},
error:
});
}
Or wrap them in a function that calls both 1 and 2.
You need to use always callback of ajax method, check out always callback of $.ajax() method http://api.jquery.com/jquery.ajax/.
The callback given to opiton is executed when the ajax request finishes. Here is a suggestion :
function function1() {
var jqxhr = $.ajax({
type: "POST",
url: "/some/page",
data: " ",
dataType: "dataType",
}).always(function (jqXHR, textStatus) {
if (textStatus == 'success') {
function2();
} else {
errorCallback(jqXHR);
}
});
}
I'm assuming you use Prototype JS and AJAX because of your tags. You should use a callback function:
function function1(callback) {
new Ajax.Request('http://www.google.nl', {
onSuccess: function(response) {
callback();
}
});
}
function function2(callback) {
new Ajax.Request('http://www.google.nl', {
onSuccess: function(response) {
callback();
}
});
}
function both() {
function1(function() {
function2();
});
}
Then use onclick="both();" on your html element.
Example: http://jsfiddle.net/EzU4p/
Ajax has async property which can be set false. This way, you can wait for that function to complete it's call and set some value. It actually defeats the purpose of AJAX but it may save your day.
I recently had similar issues and somehow calling function2 after completing function1 worked perfectly. My initial efforts to call function2 on function1 success didn't work.
$.ajax({
type: "POST",
url: "default.aspx/function1",
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false, // to make function Sync
success: function (msg) {
var $data = msg.d;
if ($data == 1)
{
isSuccess = 'yes'
}
},
error: function () {
alert('Error in function1');
}
});
// END OF AJAX
if (isSuccess == 'yes') {
// Call function 2
}

Ajax Call waiting for the response of another Ajax Call?

I have two ajax call that cannot be done in one call. When the first ajax call starts the second ajax call can start immediately or whenever the user presses a send button. If the second ajax call starts he has to wait for the response of the first ajax call because he needs data from it.
How can I achieve that the second ajax call sends his request only after the first ajax call's response has been arrived?
Is there another way than setTimeout?
Can I register a listener for ajax call 2 on ajax call 1 somehow?
My code would be:
var xhrUploadComplete = false;
// ajax call 1
$.ajax({
url: url,
type: "POST",
data: formdata,
processData: false,
contentType: false,
complete: function(response) {
var returnedResponse = JSON.parse(response.responseText);
xhrUploadComplete = true;
}
});
// ajax call 2
if (xhrUploadComplete) {
$.ajax({
url: url2,
type: "POST",
data: formdata2,
processData: false,
contentType: false,
complete: function(response) {
...
}
});
}
Edit: The second ajax call cannot be posted in done() or complete() of the first call, because it depends on the users choice to send the final form. The purpose of this two step process is to send an image to the server just after the user had inserted it to an input type=file.
Edit: In know that I cannot the the if(..) because this is an async call. I wrote it to make clear what I need to do. I think I need something like a future in Java.
xhrUploadComplete will be set to true asynchronously (in the future, when the request has finished) so your if-condition (that is evaluated right after the request is started) will never be fulfilled. You cannot simply return (or set) a value from an ajax call. Instead, move the code that waits for the results into the handler that would have set/returned the variable:
$.ajax({
url: url,
type: "POST",
data: formdata,
processData: false,
contentType: false,
complete: function(response) {
var returnedResponse = JSON.parse(response.responseText);
$.ajax({
url: url2,
type: "POST",
data: formdata2,
processData: false,
contentType: false,
complete: function(response) {
…
}
});
}
});
With the Promise pattern you can compose those even more elegantly:
$.ajax({
url: url,
type: "POST",
data: formdata,
processData: false,
contentType: false
}).then(function(response) {
var returnedResponse = JSON.parse(response.responseText);
return $.ajax({
url: url2,
type: "POST",
data: formdata2,
processData: false,
contentType: false
});
}).done(function(response) {
// result of the last request
…
}, function(error) {
// either of them failed
});
Maybe you need also need this:
var ajax1 = $.ajax({
url: url, …
}).then(function(response) {
return JSON.parse(response.responseText);
});
$(user).on("decision", function(e) { // whatever :-)
// as soon as ajax1 will be or has already finished
ajax1.then(function(response1) {
// schedule ajax2
return $.ajax({
url: url2, …
})
}).done(function(response) {
// result of the last request
…
}, function(error) {
// either of them failed
});
});

"undefined" for alerting an ajax call response , why?

i am trying to alert the return value captured by the ajax request. The web method it is refering is returning a boolean value of true or false, and when i am trying to access it outside the ajax method it gives a message "undefined" :?
<script type="text/javascript" language="javascript">
$(document).ready(function () {
var authInfo;
$.ajax({
type: "POST",
url: "service.asmx/getAuthInfo",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
authInfo = msg.d;
},
});
alert(authInfo);
});
</script>
why is the alert(authInfo) giving me as "undefined" ?? Please help !
where does this piece of code fit on the above context ?
if(auhthInfo){
$(".ansitem").editable('FetchUpdate.aspx', {
style: 'background-color:inherit;',
type: 'textarea',
indicator: '<img src="spinner.gif">',
event: 'dblclick',
onblur: 'submit',
submitdata: function (value, settings) {
return { orgval: value};
},
});
};
Your "$.ajax()" call is asynchronous, and thus the results are not available until the response is returned from the server.
If you put your "alert()" inside the "success" callback, it should work (if the HTTP transaction works).
EDITED TO HANDLE YOUR NEW CODE:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
var authInfo;
$.ajax({
type: "POST",
url: "service.asmx/getAuthInfo",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// alert(msg.d); // here it will work as it is only called when it succeeds.
MyHanlder(msg);
},
});
// alert(authInfo); // here authinfo has no value as the AJAX call may not have returned.
});
function MyHandler(msg) {
if(msg.d){
$(".ansitem").editable('FetchUpdate.aspx', {
style: 'background-color:inherit;',
type: 'textarea',
indicator: '<img src="spinner.gif">',
event: 'dblclick',
onblur: 'submit',
submitdata: function (value, settings) { return { orgval: value}; },
});
};
}
</script>
The request and the response that you get via ajax calls are asynchronous. I think it is not possible to alert the value that you get in response at the end of ready function because you are not assured that you will be getting your response before the function completes execution.
You are alerting the authInfo variable before the actual ajax call have returned. If you try this:
success:function(msg) {
authInfo = msg.d;
alert(authInfo);
}
I think you will get the correct result.
Because the AJAX call is done asynchronously, the alert does not have the value at the time of execution. If you place the alert inside the success function you should see the appropriate results. I also noticed you have an extra comma in the $.ajax parameters after the success function parameter.
It appears:
alert(authInfo);
Is running immediately when your document is ready.
However, the variable is not being initialized until after the AJAX call completes.
Try moving the alert to:
$.ajax({
type: "POST",
url: "service.asmx/getAuthInfo",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
authInfo = msg.d;
alert(authInfo);
},
});
If you need to do anything more complex with the value, you can try re-factoring the code into another function:
function onSuccess(msg)
{
if(msg.d)
{
window.alert('The value is true!');
}
else
{
window.alert('The value is false!')
}
}
$.ajax({
type: "POST",
url: "service.asmx/getAuthInfo",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: onSuccess,
});

Categories