I have a function with 3 ajax calls
var loadEditModalAddressData(){
loadCountries();
loadStates();
loadDistricts();
};
I want from js to wait, until all ajax calls are finished.
Part of my code
loadEditModalAddressData();
$(document).ajaxStop(function(){
// functionality using requested data
....
}
This worked fine, until I added extra features and figured out that $(document).ajaxStop is called after every complete request(or bunch of requests),not only in certain function scope, which mash up my code functionality.
How do I do that?
The dirty way could be to use a counter in ajaxStop to make sure all three calls have returned. A slightly better way could be to add callbacks to each of your calls and to launch the treatment when the last is received.
However, the best way is probably to use promises.
If you use jQuery to do your calls, you can do stuff like:
$.when(call1, call2, call3).then(function(results){
// your stuffs
});
Where the callX are what returns $.get (or any other jQuery promise).
Have a look here.
Use $.when to wait for multiple defereds/promises. It's synonymous to the native Promise.all().
Related
I have a couple of user interfaces where different asynchronous processes can be running simultaneously. When some of them finish, they need to do things like refresh some or all of the UI. To avoid the need to run the refresh multiple times, I use a setTimeout function to run the refresh so it runs only once even if 'triggered' from multiple simultaneous processes. e.g.:
var runCleanupTimeout;
function runCleanupOnce() {
if (runCleanupTimeout) clearTimeout(runCleanupTimeout);
runCleanupTimeout = setTimeout(function () {
refreshUI();
}, 250);
}
I know I can pass a callback into this also as well as pass the actual timeout as a variable to the function, but I'm starting to work with using Promises in functions that finish at some later time and I'm wondering how to implement such a thing as an abstract promise.
Currently I'm using a single timer (thus the static values and function calls - I seldom need more than one of these in a single UI, but when I do, I create a second variable and a second function with a fixed timeout)
I'd like to be able to write a generic utility-function as a promise so any time I want to do a run-only-once, I just call something like:
utilities.runOnce('someTimerId',250).then(
function() {
refreshUI();
}
);
I know I could instead use an array/associative array where I specify the id for the 'timer' and use a custom callback type structure. But I'm not entirely sure how this would work in a promise.then() structure. I saw one example using a .bind property but can't find a good reference on what bind() is doing in that case.
Any help to figure this out is appreciated.
Promises turned out to not be a good solution as a run-once type process only has one discreet resolve
Obvious question - why?
I need to get from external page table cell, and then inject it to the current page. Complex selectors are used.
This is with .load():
$('#check').load('https://bla-bla-bla .small:contains(Something)+.small:lt(1)');
This is with .get():
function showGetResult()
{
var result = null;
var scriptUrl = "https://bla-bla-bla";
$.get(scriptUrl, function(data) {
result = $(".small:contains(Something)", data).next().html() || "Error";
$('#check').append(result);
});
}
load() get data faster by average 1-2 seconds. But I like get() - since I can have string result, not an object.
Can someone explain why load() works faster?
Because I'd love to find the answer to this myself, I figured it would be nice to provide some resources to help:
AJAX jQuery.load versus jQuery.get:
First of all those two functions are completely different. The 'load' function works with selectors and loads the result of AJAX call inside the selected group and the callback is to handle the "oncomplete" event of the call; while the $.get function is more general and the callback handles the success response of AJAX call where you are free to define any behavior you want. And you can find all this information just by looking at the documentation and specification of the jQuery framework.
Difference between $.ajax() and $.get() and $.load()
$.get() is just a shorthand for $.ajax() but abstracts some of the
configurations away, setting reasonable default values for what it
hides from you. Returns the data to a callback. It only allows
GET-requests so is accompanied by the $.post() function for similar
abstraction, only for POST
.load() is similar to $.get() but adds functionality which allows you
to define where in the document the returned data is to be inserted.
Therefore really only usable when the call only will result in HTML.
It is called slightly differently than the other, global, calls, as it
is a method tied to a particular jQuery-wrapped DOM element.
Therefore, one would do: $('#divWantingContent').load(...)
Seems $.get and $.load both use $.ajax functionality, but in different ways. Perhaps the performance difference lies in the time it takes to parse the returned data?
Maybe the real question is how long do each of these take to send the request to the external URL (a "ping" time), and then how does that compare with processing the returned data?
In Javascript, I have two asychronous requests for data:
$.getJSON('http://foo.com', fooQuery, fooSuccess(data));
$.getJSON('http://bar.com', barQuery, barSuccess(data));
and two callbacks to process the received data:
fooSuccess(data) { // Stuff }
barSuccess(data) { // More Stuff }
How do I ensure barSuccess is executed only after fooSuccess completes?
Notes:
I want to keep the data requests as they are: asynchronous and non-blocking (since server responses may take a while).
But, I want the callbacks that process the data to be executed sequentially. That is, I do not want to execute barSuccess until fooSuccess completes.
Thanks so much for your wisdom and help!
Here is how you would do it using the jQuery deferred object that is returned by ajax requests.
var fooDfd = $.getJSON('http://foo.com', fooQuery);
var barDfd = $.getJSON('http://bar.com', barQuery);
fooDfd.then(function(fooData){
fooSuccess(fooData);
barDfd.then(barSuccess);
});
The best way would be to utilize the jQuery when().done() functionality like this:
$.when(
$.getJSON('http://foo.com', fooQuery, fooSuccess(data)),
$.getJSON('http://bar.com', barQuery, barSuccess(data))
).done(function(arg1, arg2){
fooSuccess(arg1);
barSuccess(arg2);
});
This allow simultaneous execution of the AJAX requests and guaranteed execution of the done() function once all requests has successfully completed.
I'm follow this very interesting post from a half an hour ago, when appear the elegant solution presented by #Mike Brant I quickly was to dive in the jquery library to see how the magic is made. Don't you? I recommend, is very interesting!
BTW I think we don't need all that magic, not in this case, we have two asynchronous calls handlers(functions), no matter which end first, we need to know when the second end, then all we need is a third function that will be called by the two handlers and act when all the data is ready. I know this approach will vaste four or five lines more of code than the elegant jquery solution, but at the end our brain and soul will be in better condition. Sorry my english.
Put the barSuccess call in the fooSuccess success callback.
fooSuccess(data){
jQuery.ajax({
data: data,
success: function(response){
barSuccess(data) //should still be in scope, I think?
}
}
}
This might be the opposite of my previous question here but anyway, I need to know its answer as well.
I have an Ajax call in my algorithm that I need to wait for it to run some code. There are two solutions:
1) The typical solution:
ajaxCall(function(result){
//the code to run after the call is returned
});
2) The one I'm wondering if it can be an alternative:
res=null;
ajaxCall(function(result){
res=result;
});
while(res==null)/*wait! but this will lock the GUI I guess*/;
//do the rest of the code because now res is initialized
The question is how can I write the second solution in an efficient way that doesn't freeze the GUI?
Just make the ajax call synchronous.
ref: http://developer.mozilla.org/en/XMLHttpRequest
look for the async parameter
I suggest hooking all dependent code to execute as a callback from your ajax call 's return. That way, all other javascript can continue to execute and you will not make your browser unresponsive for the duration of the call.
Alternatively, which is not something I would never ever do, you can make your ajax call synchronous, using async: false like so:
$.ajax({ url: ..., async: false });
A generic answer:
There are only two methods available in async. programming: events and callbacks. Period.
(Technically speaking, there is not really a difference between the two on the lowest level, an "event" is just a (library) function - the one doing the event "firing" - executing all functions registered as listeners so it's the same as a callback - technically, i.e. when you write event.fire() or whatever the event syntax of your preferred lib it's synchronous invocation of all registered event handler functions). When to use one or the other is a matter of preference, convention and style when designing an API.)
Javascript programming, especially AJAX, is asynchronous by definition. So if you have an algorithm that needs to "wait" for something, you're better off reconsidering the algorithm. Ironically enough, Javascript syntax is not best suitable for async programming, but there are many libraries that help you keep callbacks under control and avoid spaghetti code.
Example of callbacks spaghetti:
function ajaxRequest(url1, function() {
animateSomething(div, function() {
ajaxRequest(url2, function() {
....
})
})
})
the same with async.js looks much cleaner:
async.series([
function(_) { ajaxRequest(url1, _) },
function(_) { animateSomething(div, _) },
function(_) { ajaxRequest(url2, _) }
])
there are many ways to do this one. one of the is passing a callback to the ajax (or at least a reference of it). your code #1 would be an example of that.
another is that you have a notifier object which you add the ajax success call to it. then you can have other functions (one or more) plug into it to listen for a "success" announcement.
if i fire up 2 functions like this:
prepare_data();
read_data();
then i guess they are running at the same time. but as you can see function two is depending on the first one, so how can i make the latter one run after the first one is completed?
Javascript, and most other languages, run code sequentially.
Therefore, they will not both run at the same time.
In fact, it is not possible to run two different pieces of Javascript code at the same time. However, in many other languages, it is possible using threads.
However, if they make AJAX calls, the corresponding server-side code called by both functions will run simultaneously.
To prevent that, you'll need to make the first function accept a callback parameter and pass it the second function.
I'm assuming the first call makes some kind of asynchronous call that the second relies upon because otherwise the two functions will execute sequentially.
If so you need to do the second in the callback from the first. For example, in jQuery:
function prepare_data() {
$("#data").load("/load_data.php", function() {
read_data();
});
}
It's impossible to say how you should solve this without more information on whether you're using vanilla Javascript or a particular library. I'd strongly suggest using a library of some sort for AJAX however.
May be you want to call Second function after first function function to be successfully executed, if so, then you can do this by this
$('button').click(function()
{
function1(someVariable, function() {
function2(someOtherVariable);
});
});
function function1(param, callback) {
alert('Now first function will be called.');
callback();
}
#SLaks
In fact, it is not possible to run two
different pieces of Javascript code at
the same time. However, in many other
languages, it is possible using
threads.
Is this completely correct? cant you run javascript parallely using web workers ?
http://www.w3.org/TR/2009/WD-workers-20090423/
https://developer.mozilla.org/En/Using_web_workers