Reputation: 15058
Let's say I have a button with an event handler:
<button onclick="btnClicked()"> CLICK ME </button>
and this is the js file:
var num = 0; // global variable
function btnClicked() {
num++;
console.log(num);
}
Let's say that I clicked twice on the same button. I expect to see in console 1 and then 2.
But, it's not necessary that this is what I will get. Each button click invokes the function btnClicked
asynchronously, so there is a possible scenario that the second call will end before the first call ends. e.g. The first invocation calls btnClicked
, passes the line num++
and then holds (for some reason). Meanwhile, second invocation enters the function that num = 1, increments it to 2, prints 2 in console, and then the first invocation continues its execution with num=2 and therefore also prints 2.
Do you know any way to make sure that second invocation will occur only after first invocation ends ?
Upvotes: 2
Views: 898
Reputation: 15058
After reading the responses I understood that the scenario that I describes (console will print "2" twice) is not possible.
Event handlers are added to event queue. Event Queues are not V8 threads. Therefore, each task in event queue will execute synchronously, i.e. only after the first invocation ends the second one will start.
However, if the function were:
function btnClicked() {
num++;
console.log(num);
**AJAX call**
}
then the execution order would be: print: 1 AJAX call sent for first invocation print 2 AJAX call sent for second invocation
and then in this case both AJAX calls take place in different threads and we cannot know for sure which one of them will ends first.
Upvotes: 1
Reputation: 8689
You just need a promise for solving the order issue. Events are going each by each. But if you have an ajax request, and you need to send ajax requests each by each after you got a response from a server. And you send ajax request by a button click (asynchronous execution of functions by certain order, each by each). So here is a working example with fake execution function.
var num = 0;
var executing = new Promise(function(resolve, reject){
resolve();
});
var btnHandle = function(){
executing.then(createJobInstanse());
}
var createJobInstanse = function(){
return function(){
return new Promise(function(resolve, reject){
// fake asynchronous operation from 10ms to 2000ms, with random execution time
window.setTimeout(function(){
console.log(num++);
resolve();
}, Math.floor(Math.random() * 2000) + 10);
});
};
}
var btn = document.querySelector("#btn");
btn.addEventListener("click",btnHandle);
<button id="btn" onclick="btnHandle">click</button>
Upvotes: 0
Reputation: 1421
While it may not address your problem directly, it is recommended to use eventListener instead of onclick.
Also, to make a variable global you would call it without 'var' -- perhaps not exactly something you'd want to do with something generic like 'num', but that would make it global (more on that here).
This would give you something like:
<button id='click-me'> CLICK ME </button>
<script>
num = 0; // global variable
document.getElementById('click-me').addEventListener('click', function(){
// function here
});
</script>
Upvotes: 0
Reputation: 11
On the button click, just disable the button and at end of the function enable the button. Can you try this. I think it will work for you.
Upvotes: 0