I have a webpage, in which a certain Ajax event is triggered asynchronously. This Ajax section could be called once or more than once. I do not have control over the number of times this event is triggered, nor the timing.
Also, there is a certain code in that Ajax section that should run as a critical section, meaning, when it is running, no other copy of that code should be running.
Here is a pseudo code:
Run JavaScript or jQuery code
Enter critical section that is Ajax (when a certain process is waiting for a response callback, then do not enter this section again, until this process is done)
Run more JavaScript or jQuery code
My question is, how can I run step 2 the way described above? How do I create/guarantee a mutual exclusion section using JavaScript or jQuery.
I understand the theory (semaphores, locks, ...etc.), but I could not implement a solution using either JavaScript or jQuery.
EDIT
In case you are suggesting a Boolean variable to get into the critical section, this would not work, and the lines below will explain why.
the code for a critical section would be as follows (using the Boolean variable suggestions):
load_data_from_database = function () {
// Load data from the database. Only load data if we almost reach the end of the page
if ( jQuery(window).scrollTop() >= jQuery(document).height() - jQuery(window).height() - 300) {
// Enter critical section
if (window.lock == false) {
// Lock the critical section
window.lock = true;
// Make Ajax call
jQuery.ajax({
type: 'post',
dataType: 'json',
url: path/to/script.php,
data: {
action: 'action_load_posts'
},
success: function (response) {
// First do some stuff when we get a response
// Then we unlock the critical section
window.lock = false;
}
});
// End of critical section
}
}
};
// The jQuery ready function (start code here)
jQuery(document).ready(function() {
var window.lock = false; // This is a global lock variable
jQuery(window).on('scroll', load_data_from_database);
});
Now this is the code for the lock section as suggested using a Boolean variable. This would not work as suggested below:
The user scrolls down, (and based on the association jQuery(window).on('scroll', load_data_from_database); more than one scroll event is triggered.
Assume two scroll events are triggered right at almost the same moment
Both call the load_data_from_database function
The first event checks if window.lock is false (answer is true, so if statement is correct)
The second event checks if window.lock is false (answer is true, so if statement is correct)
The first event enters the if statement
The second event enters the if statement
The first statement sets window.lock to true
The second statement sets window.lock to true
The first statement runs the Ajax critical section
The second statement runs the Ajax critical section.
Both finish the code
As you notice, both events are triggered almost at the same time, and both enter the critical section. So a lock is not possible.
I think the most helpful information you provided above was your analysis of the locking.
The user scrolls down, (and based on the association jQuery(window).on('scroll', load_data_from_database); more than one
scroll event is triggered.
Assume two scroll events are triggered right at almost the same moment
Both call the load_data_from_database function
The first event checks if window.lock is false (answer is true, so if statement is correct)
The second event checks if window.lock is false (answer is true, so if statement is correct)
Right away this tells me that you have come to a common (and quite intuitive) misunderstanding.
Javascript is asynchronous, but asynchronous code is not the same thing as concurrent code. As far as I understand, "asynchronous" means that a function's subroutines aren't necessarily explored in depth-first order as we would expect in synchronous code. Some function calls (the ones you are calling "ajax") will be put in a queue and executed later. This can lead to some confusing code, but nothing is as confusing as thinking that your async code is running concurrently. "Concurrency" (as you know) is when statements from different functions can interleave with one another.
Solutions like locks and semaphores are not the right way to think about async code. Promises are the right way. This is the stuff that makes programming on the web fun and cool.
I'm no promise guru, but here is a working fiddle that (I think) demonstrates a fix.
load_data_from_database = function () {
// Load data from the database. Only load data if we almost reach the end of the page
if ( jQuery(window).scrollTop() >= jQuery(document).height() - jQuery(window).height() - 300) {
console.log(promise.state());
if (promise.state() !== "pending") {
promise = jQuery.ajax({
type: 'post',
url: '/echo/json/',
data: {
json: { name: "BOB" },
delay: Math.random() * 10
},
success: function (response) {
console.log("DONE");
}
});
}
}
};
var promise = new $.Deferred().resolve();
// The jQuery ready function (start code here)
jQuery(document).ready(function() {
jQuery(window).on('scroll', load_data_from_database);
});
I'm using a global promise to ensure that the ajax part of your event handler is only called once. If you scroll up and down in the fiddle, you will see that while the ajax request is processing, new requests won't be made. Once the ajax request is finished, new requests can be made again. With any luck, this is the behaviour you were looking for.
However, there is a pretty important caveats to my answer: jQuery's implementation of promises is notoriously broken. This isn't just something that people say to sound smart, it is actually pretty important. I would suggest using a different promise library and mixing it with jQuery. This is especially important if you are just starting to learn about promises.
EDIT: On a personal note, I was recently in the same boat as you. As little as 3 months ago, I thought that some event handlers I was using were interleaving. I was stupefied and unbelieving when people started to tell me that javascript is single-threaded. What helped me is understanding what happens when an event is fired.
In syncronous coding, we are used to the idea of a "stack" of "frames" each representing the context of a function. In javascript, and other asynchronous programming environments, the stack is augmented by a queue. When you trigger an event in your code, or use an asynchronous request like that $.ajax call, you push an event to this queue. The event will be handled the next time that the stack is clear. So for example, if you have this code:
function () {
this.on("bob", function () { console.log("hello"); })
this.do_some_work();
this.trigger("bob");
this.do_more_work();
}
The two functions do_some_work and do_more_work will fire one after the other, immediately. Then the function will end and the event you enqueued will start a new function call, (on the stack) and "hello" will appear in the console. Things get more complicated if you trigger an event in your handler, or if you trigger and event in a subroutine.
This is all well and good, but where things start to get really crappy is when you want to handle an exception. The moment you enter asynchronous land, you leave behind the beautiful oath of "a function shall return or throw". If you are in an event handler, and you throw an exception, where will it be caught? This,
function () {
try {
$.get("stuff", function (data) {
// uh, now call that other API
$.get("more-stuff", function (data) {
// hope that worked...
};
});
} catch (e) {
console.log("pardon me?");
}
}
won't save you now. Promises allow you to take back this ancient and powerful oath by giving you a way to chain your callbacks together and control where and when they return. So with a nice promises API (not jQuery) you chain those callbacks in a way that lets you bubble exceptions in the way you expect, and to control the order of execution. This, in my understanding, is the beauty and magic of promises.
Someone stop me if I'm totally off.
I would recommend a queue which only allows one item to be running at a time. This will require some modification (though not much) to your critical function:
function critical(arg1, arg2, completedCallback) {
$.ajax({
....
success: function(){
// normal stuff here.
....
// at the end, call the completed callback
completedCallback();
}
});
}
var queue = [];
function queueCriticalCalls(arg1, arg2) {
// this could be done abstractly to create a decorator pattern
queue.push([arg1, arg2, queueCompleteCallback]);
// if there's only one in the queue, we need to start it
if (queue.length === 1) {
critical.apply(null, queue[0]);
}
// this is only called by the critical function when one completes
function queueCompleteCallback() {
// clean up the call that just completed
queue.splice(0, 1);
// if there are any calls waiting, start the next one
if (queue.length !== 0) {
critical.apply(null, queue[0]);
}
}
}
UPDATE: Alternative solution using jQuery's Promise (requires jQuery 1.8+)
function critical(arg1, arg2) {
return $.ajax({
....
});
}
// initialize the queue with an already completed promise so the
// first call will proceed immediately
var queuedUpdates = $.when(true);
function queueCritical(arg1, arg2) {
// update the promise variable to the result of the new promise
queuedUpdates = queuedUpdates.then(function() {
// this returns the promise for the new AJAX call
return critical(arg1, arg2);
});
}
Yup, the Promise of cleaner code was realized. :)
You can wrap the critical section in a function and then swap the function so it does nothing after first run:
// this function does nothing
function noop() {};
function critical() {
critical = noop; // swap the functions
//do your thing
}
Inspired by user #I Hate Lazy Function in javascript that can be called only once
Related
Good afternoon guys -
Is there a well known way to check if a $.ajax call has finished?
-- FOR INSTANCE --
Let's say I'm using a $.ajax call to load in a large number of leaflet polygons from a .geojson file (asynchronously as a layer group). Under normal circumstances, this happens almost immediately - but the user has elected to load a large job this time around. The user has assumed that the set of polygons has been loaded and attempts to do something with this group of layers prematurely - only to find that nothing happens (the layer group doesn't actually exist yet in the browser).
My intuition (I'm new to web development) is to have some sort of global flag that's set for the dependent algorithm to check. We would set the flag prior to loading the layers, and then change it to some other value in the .done({}) section of the $.ajax call.
-- UPDATE --
I've reworked the code to allow users to choose whether or not they wish to retry the request, and also force the browser to wait some time before retrying the request.
However, I've also found the the issue seems to be with Chrome. Firefox appears to be able to handle the $.ajax.always callback as soon as it finishes (in other words, the $.ajax.always callback will interrupt the regular flow of javascript).
Chrome appears to block the $.ajax.always callback and only lets it execute after all other javascript has finished running (no interrupt).
This particular question stemmed from a debug case that automated user input from within a loop - and since Chrome doesn't call the $.ajax.always callback until the current process is complete, the process isn't marked as completed.
Example Code:
procBox = []; // Global scope, stands for Process Box
function loadPolygons() {
procBox["loadPolygons"] = "running";
$.ajax({
// ajax things here
}).done(function() {
procBox["loadPolygons"] = "done";
}).fail(function() {
// failure stuff here
});
}
function dependentFunction() {
if procBox["loadPolygons"] === "done") {
// The meat of the function (dependentFunction things here)
} else {
// Backup case that allows the browser to retry the request
/* --
* If this fires, the server is still trying to process the
* ajax request. The user will be prompted to retry the request,
* and upon agreement, the function will be called again after
* 1 second passes.
*/
var msg = "Oops! It looks like we're still fetching your "
+ "polygons from the server. Press OK to retry.";
if (confirm(msg)) {
setTimeout(dependentFunction, 1000);
}
}
}
This approach seems to work well in Firefox - the alert() stops JavaScript execution and gives it a chance for the .done({}) callback to occur. But for some reason, the while loop never allows the .done({}) callback to complete in Chrome!
Does anyone know of a better approach for this than using flags or async: false?
I appreciate any answers and knowledge out there!
There are numerous ways to do :
as already sugegsted you can use
since you use jQuery, you can use custom events https://learn.jquery.com/events/introduction-to-custom-events/:
$(document).on("myajax:done", function(){ dependentFunction();})
$.ajax({...}).done(function(){
$(document).trigger("myajax:done")
});
or even global ajax events
https://api.jquery.com/category/ajax/global-ajax-event-handlers/
but really consider why not to do something like
procBox = {onLoadPolygons:dependentFunction}; // Global scope
function loadPolygons() {
$.ajax({
// ajax things here
}).done(function() {
procBox["onLoadPolygons"]();
}).fail(function() {
// failure stuff here
});
}
function dependentFunction() {
alert("Please wait for the polygons to load");
dependentFunctionThings();
}
function dependentFunctionThings(){
// Do dependent function things...
}
UPD:
if you ensist on your structure, and still want to use blocking function
use setInterval to perform check
function dependentFunction() {
var h = setInterval(function() {
if (procBox["loadPolygons"] == "done") {
clearInterval(h);
// Do dependent function things...
}
}, 100);
}
Or wrap it up into a Promise (http://caniuse.com/#feat=promises)
function dependentFunction() {
(new Promise(function(resolve) {
var h = setInterval(function(){
if (procBox["loadPolygons"] == "done") {
clearInterval(h);resolve();
}
}, 100);
})).then(function(){
// Do dependent function things...
});
}
But I still believe that something wrong in your structure
From the docs :
.ajaxComplete()
Whenever an Ajax request completes, jQuery triggers the ajaxComplete event. Any and all handlers that have been registered with the .ajaxComplete() method are executed at this time.
http://api.jquery.com/ajaxcomplete/
I have a bootstrapped extension which interacts with the chrome part of Firefox (i.e. even before the content loads), and needs to query an SQLite database for some check. I would prefer a sync call. But, since a sync call is bad in terms of performance and can cause possible UI issues, I need to make an async DB call.
My use case is such:
Make aysnc call to database
Once completed do further processing
Now, this can be easily handled by placing 'further processing' part in handleCompletion part of executeAsync function.
But, I want the 'further processing' to be done irrespective of this statement being executed i.e. This DB lookup may or may not happen. If it doesn't happen well and good, go ahead. If it does I need to wait.
So, I am using a flag based strategy; I set a flag handleCompletionCalled in handleError & handleCompletion callback to true.
In the further processing part, I do a
while(handleCompletionCalled) {
// do nothing
}
//further processing
Is this a good strategy or can I do something better ( I don't really want to use Observers, etc. for this since I have many such cases in my entire extension and my code will be filled with Observers)?
Using a while loop to wait is a seriously Bad Idea™. If you do, the result will be that you hang the UI, or, at a minimum, drive CPU usage through the roof by rapidly running though your loop a large number of times as fast as possible.1
The point about asynchronous programming is that you start an action and then another function, a callback, is executed once the activity is completed, or fails. This either allows you to start multiple actions, or to relinquish processing to some other part of the overall code. In general, this callback should handle all activity that is dependent on the completion of the asynchronous action. The callback function, itself, does not have to include the code to do the other processing. After it has done what needs to happen in response to the async action completing, it can just call another function like doOtherProcessing().
If you launch multiple asynchronous, actions you can then wait for the completion of all of them by having flags for each task and a single function that is called at the end of all the different callback functions like:
function continueAfterAllDone(){
if(task1Done && task2Done && task3Done && task4Done) {
//do more processing
}else{
//Not done with everything, yet.
return;
}
}
This could be extended to an arbitrary number of tasks by using an array, or task queue, which the function then checks to see if all of those are completed rather than a hard-coded set of tasks.
Waiting:
If you are going to have another processing path which executes, but then must wait for the completion of the asynchronous action(s), you should have the wait performed by setting up a timer, or interval. You then yield the processor for a specified period of time until you check again to see if the conditions you need to proceed have occurred.
In a bootstrapped add-on, you will probably need to use the nsITimer interface to implement a timeout or interval timer. This is needed because at the time you are running your initialization code it is possible that no <window> exists (i.e. there may be no possibility to have access to a window.setTimeout()).
If you are going to implement a wait for some other task, you could do it something like:
const Cc = Components.classes;
const Ci = Components.interfaces;
var asyncTaskIsDone = false;
var otherProcessingDone = false;
// Define the timer here in case we want to cancel it somewhere else.
var taskTimeoutTimer;
function doStuffSpecificToResultsOfAsyncAction(){
//Do the other things specific to the Async action callback.
asyncTaskIsDone = true;
//Can either call doStuffAfterOtherTaskCompletesOrInterval() here,
// or wait for the timer to fire.
doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval();
}
function doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval(){
if(asyncTaskIsDone && otherProcessingDone){
if(typeof taskTimeoutTimer.cancel === "function") {
taskTimeoutTimer.cancel();
}
//The task is done
}else{
//Tasks not done.
if(taskTimeoutTimer){
//The timer expired. Choose to either continue without one of the tasks
// being done, or set the timer again.
}
//}else{ //Use else if you don't want to keep waiting.
taskTimeoutTimer = setTimer(doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval
,5000,false)
//}
}
}
function setTimer(callback,delay,isInterval){
//Set up the timeout (.TYPE_ONE_SHOT) or interval (.TYPE_REPEATING_SLACK).
let type = Ci.nsITimer.TYPE_ONE_SHOT
if(isInterval){
type = Ci.nsITimer.TYPE_REPEATING_SLACK
}
let timerCallback = {
notify: function notify() {
callback();
}
}
var timer = Cc["#mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(timerCallback,delay,type);
return timer;
}
function main(){
//Launch whatever the asynchronous action is that you are doing.
//The callback for that action is doStuffSpecificToResultsOfAsyncAction().
//Do 'other processing' which can be done without results from async task here.
otherProcessingDone = true;
doStuffAfterBothAsyncAndOtherTaskCompletesOrInterval();
}
Initialization code at Firefox startup:
The above code is modified from what I use for delaying some startup actions which do not have to be done prior to the Firefox UI being displayed.
In one of my add-ons, I have a reasonable amount of processing which should be done, but which is not absolutely necessary for the Firefox UI to be shown to the user. [See "Performance best practices in extensions".] Thus, in order to not delay the UI, I use a timer and a callback which is executed 5 seconds after Firefox has started. This allows the Firefox UI to feel more responsive to the user. The code for that is:
const Cc = Components.classes;
const Ci = Components.interfaces;
// Define the timer here in case we want to cancel it somewhere else.
var startupLaterTimer = Cc["#mozilla.org/timer;1"].createInstance(Ci.nsITimer);
function startupLater(){
//Tasks that should be done at startup, but which do not _NEED_ to be
// done prior to the Firefox UI being shown to the user.
}
function mainStartup(){
let timerCallback = {
notify: function notify() {
startupLater();
}
}
startupLaterTimer = startupLaterTimer.initWithCallback(timerCallback,5000
,Ci.nsITimer.TYPE_ONE_SHOT);
}
Note that what is done in startupLater() does not, necessarily, include everything that is needed prior to the ad-on being activated by the user for the first time. In my case, it is everything which must be done prior to the user pressing the add-on's UI button, or invoking it via the context menu. The timeout could/should be longer (e.g. 10s), but is 5s so I don't have to wait so long for testing while in development. Note that there are also one-time/startup tasks that can/should be done only after the user has pressed the add-on's UI button.
1. A general programming issue here: In some programming languages, if you never yield the processor from your main code, your callback may never be called. In such case, you will just lock-up in the while loop and never exit.
I'd like to be able to dispatch a bunch of work via JavaScript to be done in the browser in such a way that the browser stays responsive throughout.
The approach I'm trying to take is to chunk up the work, passing each chunk to a function that is then queued with a setTimeout(func, 0) call.
I need to know when all the work is done, so I'm storing the returned timer ID in a map (id -> true|false). This mapping is set to false in the next block of code after I have the timer ID, and the queued function sets the mapping to true when it completes... except, of course, the queued function doesn't know its timer ID.
Maybe there's a better/easier way... or some advice on how I can manipulate my map as I need to?
I would queue the work in an array, use one timeout to process the queue and call a callback once the queue is empty. Something like:
var work = [...];
var run = function(work, callback) {
setTimeout(function() {
if(work.length > 0) {
process(work.shift());
setTimeout(arguments.callee, 25);
}
else {
callback();
}
}, 25);
};
run(work, function() {
alert('Work is done!');
});
As JavaScript in browsers is single threaded there is no real advantage to run multiple timeouts (at least I think this is what you are doing). It may even slow down the browser.
I'd like to add that although javascript is single threaded you can still have multiple ajax calls going at once. I recently had a site that needed to do potentially hundreds of ajax calls and the browser just couldn't handle it. I created a queue that used setTimeOut to run 5 calls at once. When one of the ajax calls returned it fired a callback (which is handled by a single thread) and then made the next call on the stack.
Imagine you're a manager that can only talk to one person at a time, you give 5 employees assignments, then wait for their responses, which may come in any order. Once the first employee comes back and gives you the information, you give them a new assignment and wait for the next employee (or perhaps even the same employee) to come back. So although you're "single threaded" 5 things are going on at once.
There is an example right in the HTML Standard, how it is best to handle it:
To run tasks of several milliseconds back to back without any delay,
while still yielding back to the browser to avoid starving the user
interface (and to avoid the browser killing the script for hogging the
CPU), simply queue the next timer before performing work:
function doExpensiveWork() {
var done = false;
// ...
// this part of the function takes up to five milliseconds
// set done to true if we're done
// ...
return done;
}
function rescheduleWork() {
var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
if (doExpensiveWork())
clearTimeout(handle); // clear the timeout if we don't need it
}
function scheduleWork() {
setTimeout(rescheduleWork, 0);
}
scheduleWork(); // queues a task to do lots of work
The moment of finishing the work is pretty clear, when clearTimeout is called.
Is there a way to delay the calling of a JavaScript function until two criteria are met?
I have a slideUp() animation and a .get() function that start at the same time, but either one could finish first. I want a function to be called when both have completed.
You just have to keep track, either a counter or (my preferred approach) flags for all relevant information.
var slideDone, getDone;
$("#foo").slideUp(function() {
slideDone = true;
nextThing();
});
$.get({
// ...
success: function() {
getDone = true;
nextThing();
}
});
function nextThing() {
if (slideDone && getDone) {
// Do the next thing
}
}
Now, obviously my two conditions above are very artificial, but I find that most of the time when this comes up in my real work, I have actual information I can use for the check and so don't resort to artificial conditions.
Or a counter:
var counter = 0;
++counter;
$("#foo").slideUp(function() {
nextThing();
});
++counter;
$.get({
// ...
success: function() {
nextThing();
}
});
function nextThing() {
if (--counter === 0) {
// Do the next thing
}
}
To someone used to multi-threaded programming, that looks like a race condition (what if the slideUp completes before we start the get?), but it's not one in JavaScript on browsers, which is single-threaded (barring the use of web workers, which use a syntax that wouldn't apply to the above anyway).
If you find this coming up a lot, you could of course always isolate the logic (not that there's a lot of it, but...) into an object and reuse it.
You could create a simple boolean variable which both delegate methods have acesss to and check whether the previous method has executed.
This way you can check in your delegate functions if the previous function has completed and execute some method.
T.J. Crowders answer includes some good example code of this approach.
You can use jQuery's Deferred Object:
http://api.jquery.com/category/deferred-object/
It's actually perfect for what you need. You can set a function to only execute when all the deferred objects bound to it get resolved. Some of jQuery's native functions return a deferred object by default such as the $.ajax and I believe animations as well (the latest version of jQuery at least)
Read the docs, it'll do a much better job at explaining it than I could.
I'm trying to figure the best way to get my functions executing in the correct order.
I have 3 functions
function 1 - squirts OPTIONs into a SELECT via JSON and marks them as selected
function 2 - squirts OPTIONS into a 2nd SELECT and marks them as selected
function 3 - gets the values from the above SELECTs along with some additional INPUT values, does an AJAX GET resulting in JSON data, which is read and populates a table.
With JQuery Onload, I execute:
function1();
function2();
function3();
I'm finding function3 is executing before the SELECTs have been populated with OPTIONS and hence the table has no results, because the values sent in the GET were blank.
I know this is probably a very simple problem and that there are probably a dozen ways to accomplish this, but basically I need the best way to code this so that function3 only runs if function1 and 2 are complete.
I've come into Javascript via the back door having learnt the basics of JQuery first!
Thanks for your assistance.
Javascript executes synchronously, which means that function3 must wait for function2 to complete, which must wait for function1 to complete before executing.
The exception is when you run code that is asynchronous, like a setTimeout, setInterval or an asynchronous AJAX request.
Any subsequent code that relies on the completion of such asynchronous code needs to be called in such a manner that it doesn't execute until the asynchronous code has completed.
In the case of the setTimeout, you could just place the next function call at the end of the function you're passing to the setTimeout.
In the case of an AJAX call, you can place the next function call in a callback that fires upon a completed request.
If you don't want the execution of the subsequent function to occur every time, you can modify your functions to accept a function argument that gets called at the end of the asynchronous code.
Something like:
function function1( fn ) {
setTimeout(function() {
// your code
// Call the function parameter if it exists
if( fn ) {
fn();
}
}, 200);
}
function function2() {
// some code that must wait for function1
}
onload:
// Call function1 and pass function2 as an argument
function1( function2 );
// ...or call function1 without the argument
function1();
// ...or call function2 independently of function1
function2();
I recommend you use a Promises library. You can hack simple solutions like other answers suggest, but as your application grows, you'll find you are doing more and more of these hacks. Promises are intended to solve these kinds of problems when dealing with asynchronous calls.
The CommonJS project has several Promises proposals which you should check out. Here is a question I asked on SO about Promises a while back with links to other solutions. Learn more about Promises in this Douglas Crockford video. The whole video is good, but skip to just past half way for promises.
I'm using the FuturesJS library currently as it suits my needs. But there are advantages to other implementations as well. It allows you to do sequences very easily:
// Initialize Application
Futures.sequence(function (next) {
// First load the UI description document
loadUI(next); // next() is called inside loadUI
})
.then(function(next) {
// Then load all templates specified in the description
loadTemplates(next); // next() is called inside loadTemplates
})
.then(function(next) {
// Then initialize all templates specified in the description
initTemplates();
});
Even more powerful is when you need to join async events together and do another action when all of the other async events have completed. Here's an example (untested) that will load a bunch of HTML files and then perform an action only once ALL of them have completed loading:
var path = "/templates/",
templates = ["one.html","two.html","three.html"],
promises = [];
$.each(templates, function(i,name) {
promises[i] = Futures.promise();
var $container = $("<div>");
$container.load(path+name, function(response,status,xhr) {
promises[i].fullfill();
}
});
Futures.join(promises, {timeout: 10000}) // Fail if promises not completed in 10 seconds
.when(function(p_arr) {
console.log("All templates loaded");
})
.fail(function(p_arr) {
console.log("Error loading templates");
});
This might be overkill for your application. But if the application is growing in complexity, using promises will help you in the long run.
I hope this helps!
invoke function2 inside of function1 and function3 inside of function2.
It's not clear why f1 and f2 are executing before f3.
Also, are you using the preferred $(document).ready() or some variation of onload?
It might be helpful if you provide a reproducible test case.
fun3() will only run after both are ready. It might run twice. You can fix this with a lock inside fun3() you would need a Singleton to guarantee it works correctly.
var select1ready = false, select2ready = false;
fun1()
{
// do stuff
select1ready = true;
fun3();
}
fun2()
{
// do stuff
select2ready = true;
fun3();
}
fun3()
{
if (select1ready && select2ready)
{
}
}
fun1();
fun2();