Need to wait until XMLHttpRequest completes - javascript

Whenever I try to find answer of this question everyone refers to ajax start/stop etc.
I am using XUI JS's XHR function for cross domain calling, now I want exactly like this
callMyXHRfunction();
callNextFunctionWhenAboveFunctionResponded();
i.e. I should move forward until unless my xhr function responds (either success or failure)
Update
Use Case:
There is a function called getAllData(), this function get all my current data submitted to server. I need to call this function often to get the latest data and move ahead. While loggin I call this function to get latest data and after every 10 mins I need to call this to get data refreshed.
So if I call each my function on success function then my code may confuse other developer and if I write like above he/she will easily know what is going on in first line and in 2nd line.
Hope now everyone understand my situation very well.

See third example on the website you are referencing:
x$( selector ).xhr( url, fn );
Second argument can be a callback, callback being the keyword you were probably looking for to begin with.
Alternatively, use a synchronous call by supplying async: false as an option.
x$("body").xhr("http://the-url",{ async: false });
Control flow will pause until the request returned and only then continue with your next function. See http://jsfiddle.net/ZQ9uw/ for reference.

You need to make the .xhr call in a way that specifies a callback function and pass in your "next" function as the callback.
So you'd write it like this:
callMyXHRFunction(nextFunctionToCall); // no parens after nextFunctionToCall!
function callMyXHRFunction(callback) {
$("something").xhr(url, {
error: callback, // so that nextFunctionToCall is called on error
callback: callback, // so that nextFunctionToCall is called on success
async: true
// add more options here
});
}

Related

What are callback function?

I ask a friend and ask what is (data, function(i,e) in this code and he said this is callback then i search the internet about callback and doesn't understand it. I read about this What are callback methods?what is callback in simpliest way ?
$.each(data, function(i,e){
console.log(e.id);
});
What is the use of (data, function(i,e) here?
$.ajax({
type: "GET",
url: pbxApi+"/confbridge_participants/conference_participants.json?cid="+circle,
dataType: "jsonp",
jsonpCallback: 'callback',
contentType: "application/javascript",
success: function(data) {
console.log(data);
}
});
A callback function is a function you specify to an existing function/method, to be invoked when an action is completed, requires additional processing, etc.
*Here's a little something for you to understand callbacks better:
Guy 1 to Guy 2: hey dude I wanna do something when a user clicks in there, call me back when that happens alright?
Guy 2 calls back Guy 1 when a user clicks here.*
A callback method which is called back.
Who calls it back at you ?
Your framework calls it back.
Why it calls it back ?
Because you ask for it to get called back because you want to do some processing when something happens.
Examples
You are doing some processing and don't know when it completes. You provide a callback , and you continue with some other work. Your call-back function will be called back to tell you that processing is finished and you can do something at your end now.
You want to know when some control fires some event so that you can do some processing. You provide a call-back function as event handler.
You are not happy with default processing done by framework and want to override that processing, you provide a call-back and framework calls it back to use your own processing.
So, in general : You ask a component/framework to call your provided method. You never call that provided method from your code, someone else calls it back.
A callback function is a function that is passed to another function as a parameter, and the callback function is called (or executed) inside the another Function.
Like this
(data, function(i,e)
We can pass functions around like variables and return them in functions and use them in other functions. When we pass a callback function as an argument to another function, we are only passing the function definition.
Note that the callback function is not executed immediately. It is “called back” at some specified point inside the containing function’s body. For more info Refer Here
Normally, JavaScript statements are executed line by line. However, with effects, the next line of code can be run even though the effect is not finished. This can create errors.
To prevent this, you can create a callback function.
A callback function is executed after the current effect is finished.
For e.g, this is a call back function:
$("button").click(function(){
$("p").hide("slow", function(){
alert("The paragraph is now hidden");
});
});
In this case the function hide will be executed before that alert which is precisely what we want.
On the other hand if you don't use call back function say this way:
$("button").click(function(){
$("p").hide(1000);
alert("The paragraph is now hidden");
});
In this case alert will be executed even before the function hide is executed. This is the typical use of callback function in Javascript.

$.ajax() callbacks are not bound to their specific request?

The code is very complex so i have simplified below in order to confirm if the behavior i am experiencing is normal or due so some other error i have made in the code.
I have two separate ajax requests that each have their own unique call back. I do not care which one completes first and one has no dependency on the other
function ajax(url, cbS){
$.ajax({
url: url,
contentType: 'application/json',
dataType: 'json',
success: function(data){
cbS(data)
},
});
}
function callbackSuccess1(data){
$('#div1').html(data)
}
function callbackSuccess2(data){
$('#div2').html(data)
}
//request#1
ajax(myapiurl+'&peram1=100', callbackSuccess1);
//request#2
ajax(myapiurl+'&peram2=200', callbackSuccess2);
The problem: Sometimes callbackSuccess1 gets the data intended for request#2 and vice versa.
It seems that which ever request completes first fires callbackSuccess1 and the second to complete fires callbackSuccess2.
I need the callback to be bound to it's specific request so that regardless of the order in which they complete each request fires it's proper callback.
OTHER INFO: My backed is django-tastypie, at this point i am thinking that tastypie is somehow messing up the response. That is the only logical conclusion, given that the javascript seems to be immutable.
The proof that this is actually occurring is that when i inspect the responce on request#1 the data objects are clearly intended for request#2...
CONCLUSION:
Thanks for confirming that 'each invocation of your ajax() function will create it's own closure'. This was what i thought was going wrong. I found the problem in my API. I was doing some funky stuff and it looks like I had a variable that was not getting trashed in time causing the API to return the wrong data if the first request took longer than the second.
The only issue I see with the code you have included is that the function argument is cbS, but you are calling cbs(data) - note the different capitalization.
Other than that, each invocation of your ajax() function will create it's own closure and have it's own arguments and those arguments will be preserved separately for the internal success callback. This is an important capability in javascript and it works. It does not get the arguments of one call confused with the callback of another as long as you are not using any global variables or state that might change during the execution of the asynchronous ajax call.
You could probably use jsonp and specify callback query parameter in URL for $.ajax
callback would be the name of javascript function which is to be invoked whenever the response is returned from server.
For more details please refer jquery doc : http://api.jquery.com/jQuery.ajax/
For theory : http://en.wikipedia.org/wiki/JSONP
This is mainly used for cross-site ajax calls.

How to make function that returns it's inner-function's value?

It's probably obvious to you, but I can't figure it out.
I need to make function that returns it's inner-function's value. In other words, I have function get_users() that must return JSON object. That JSON object is got by $.post (built-in jQuery).
function get_users() {
return
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
return response;
},
'json'
);
}
(above is what I tried to do, but it returned undefined - what a surprise)
Because of variable scope, I cannot just make variable in inner-function because it won't be visible in main function. I don't want to use global variables neither. Looking for better solution!
Thanks in any advice!
Why are you fighting against the asynchronous nature of AJAX? When you do AJAX you should get accustomed to work with events and callbacks instead of writing sequential code. You can't return the inner contents. The simple reason for this is that this inner function could execute much later than the outer function. So the outer function will return a result much before the success callback executes.
So here's the correct way:
function get_users() {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
// instead of trying to return anything here
// simply do something with the response
// Depending on what the server sent you there
// will be different ways.
// Here you could also call some other custom function
// and pass it the response
}
'json'
);
}
You can't return values from ajax calls. (Without setting async false, but that wouldn't really be ajax)
By the time you hit the inner return, the outer function has already completed
You will need to use a callback to process the users.
get_users(function(response) { // this anonymous function is passed in as a parameter
// do something with the response
});
function get_users(callback) {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
// call the passed in function and pass in the response as a parameter
callback(response);
},
json'
);
}
You need a primer on how asynchronous ajax calls work.
When you call $.post(), it starts a networking call to do the post and immediately returns from the $.post() call and continues executing the rest of your javascript. It will even exit your function get_users() right away.
But, the ajax call is not yet done - it's still in progress. Some time later, the ajax call will finish and when that happens the success handler for the ajax call that you have defined as function(response) {...} will get called. Only then, at that later time, is the response value from the ajax call known.
This is what asynchronous ajax means. You cannot write a call like get_users() and expect it to get the users and return with them. Instead, you have to make use of callback functions that will get called some time later (when the ajax has completed) and you can continue the path of your code then. Yes, this is inconvenient, but it's how things work in javascript with asynchronous ajax calls. The benefit of asynchronous ajax calls is that the browser and other javascript code can be fully live while the ajax call is underway. The cost of asynchronous ajax calls is that coding for them is more complicated.
You have a number of choices for how to deal with this complication. First off, you can make your get_users() call and then just continue the programming sequence that you want to carry out in the internal callback inside of get_users() since that's the only place that the response (the actual users) is known. If you're only using get_users() in one place in your code, then that could work fine. It would look like this:
function get_users() {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
function(response) {
// process the user list here and continue whatever other code you
// need that deals with the user list
},
'json'
);
}
If you need to use get_users() in several different places for different purposes, then you can change it to take a callback itself and let the post call just call that callback when the ajax call is done. You would then complete your processing of the response in that callback function:
function get_users(callback) {
$.post(
url_base + 'travel/trip/get_users/' + trip_id,
callback,
'json'
);
}
In this second option you could call get_users() like this:
get_users(function(response) {
// process the user list here and continue whatever other code you
// need that deals with the user list
});
There are even more advanced options available using jQuery's deferred object.

send $.post() one at a time ("adding a pause" but really: toggling a 'transmit' flag)

in jQuery, I iterate over an xml list of areas and do a POST request to get detailed information about each area. Because sending thousands of requests at once is debilitating for the client and server, I would like to set a flag so that I wait for a request to finish before sending the subsequent [next] request.
if the xml looks like this:
<area>5717</area>
<area>5287</area>
<area>5376</area>
then the xml parsing kinda looks like:
$(xml).find("area").each( function() {
doPost();
}
and the doPost() function looks like
doPost : function () {
$.post( ... )
}
Basically, I would like to add a toggling "wait" but I'm not sure how to achieve this. Is there a way I can keep the essential ".each" iteration or is another type of loop better for this?
Thanks in advance.
A general algorithm off the top of my head:
You could put the whole list into an array. Take the first item of the array and post it. In the success handler of your post you could recursively call the function with the next index int the list.
I wouldn't use async: false because it would then be a blocking operation, which I assume the OP doesn't want.
You can use:
$.ajaxSetup({async:false});
at the top of your script to make your AJAX calls synchronous.
Alternately, you can replace $.post() with $.ajax() and set the async flag to false.
can you do a setTimeout ? that will allow for the function to still process asynchronous and allow for you to wait for some time in there too.
http://www.w3schools.com/js/js_timing.asp
setTimeout(function() {}, 5000)
You can refactor your doPost() function to take the <area> element to process as an argument, and chain into the next element from your success callback. Something like:
(function doPost($area) {
if ($area.length > 0) {
$.post({
// your options,
success: function() {
// your success handling...
doPost($area.next("area"));
}
});
}
})($(xml).find("area").first());
EDIT: Maybe the code above was a little too compact indeed.
Basically, the aim is to refactor your function so that it takes a jQuery object containing the next <area> element to process, or nothing if processing should stop:
function doPost($area) {
if ($area.length > 0) {
// Perform POST request and call ourselves from success callback
// with next <area> element (or nothing if there's no such element).
}
}
Then call this function with the first <area> element to process:
doPost($(xml).find("area").first());
The first code fragment in my answer does both at the same time. Functions are first-class objects in Javascript, and you can call a function you've just defined by enclosing its definition with parenthesis and providing the usual argument list, also surrounded by parenthesis.

How to use callback function in JavaScript functions

I am very new to JavaScript and need to use callback function in my java script function. I don't know how to use a callback function. Below is my code:
function SelectedFeature() {
// Here is my code call_Method1();
call_Method2();
}
The problem in the above function is that, call_method2() starts executing before call_Method1() ends its execution. To solve this problem, someone told me to use a callback function. Now how can I use callback function in my SelectedFeature() function? Please explain by using code sample.
I'm making an asynchronous request in call_method1(). I need call_Method2() should be called after completing execution call_method1(). But in my case, call_method2() calls before call_method1() completes its execution. Now how can I fix this?
You have to refactor call_method1() to accept and execute a callback after it finished execution:
call_method1(call_method2);
and
function call_method1(callback) {
// ...
// do asynchronous stuff, when the response is processed, call
if(typeof callback === 'function') {
callback();
}
// ...
}
Functions are first class citizens, so by referring to them by their name, you can pass them around like any other value.
We could help better if you post the code for call_method1.
What are you using to do your asynchronous call? Did you code it yourself or are you using a library like JQuery?
You could simply put a bool to say "working" that you set to true as method 1 starts and back to false when it finishes. you could then have method2 wait while working is true.
The question has already been answered above by Felix. Inspired by his answer and an issue I am having in a current project, I wrote a little gist that has a class that adds up a little extra safety.
To sum up, you pass a callback function just as the way you pass a variable. Then the receiver will trigger it as a function.
myCoolFunction: function( data ) {
// Do some thing with response
}
$.get( '/some/cool/url', myCoolFunction );
In the above $.get calls back myCoolFunction with the parameter data once the data is fetched
What happens if myCoolFunciton is a variable. Well it depends on how the receiver handles the input.
Just to be careful, I have a CoffeeScript class ( and its JavaScript compilation ) that will do some safety checks.
It doesn't do any thing magic, checks if its a function and returns, if not returns an empty function so that it would reduce possibility of JS error. https://gist.github.com/ziyan-junaideen/8717925

Categories