Prevent second execution until the first ends in jquery - javascript

I have the following code...
$("#myID").click(function(){
//do some ajax requisition here
//make it appears in screen with a fadeIn(300)
});
#myID is an id of one tag
But i need that this function was not called again until the actual execution ends, i tried put many different code before e after the comments but with no success, if you can help me to prevent that second execution!
The fadeIn() don't hold the execution, the code after it was executed while the effect is occurring, can someone help me?
Thanks

You can set a flag that stores the state of whether or not the AJAX function is running:
$(function () {
//set flag to allow AJAX calls
var AJAX_ok = true;
//bind click event handler
$("#myID").click(function(){
//check if it is ok to run an AJAX request right now
if (AJAX_ok === true) {
//if we can run an AJAX request then set the AJAX_ok flag to false so another one does not start
AJAX_ok = false;
//make the AJAX call
$.getJSON('<url>', function (data) {
//now that the callback function has been called, the AJAX call is done, so we re-enable the AJAX_ok flag
AJAX_ok = true;
//make it appears in screen with a fadeIn(300)
//if DATA is valid HTML then...
$(data).css('display', 'none').appendTo('#some-container').fadeIn(300);
});
}
});
});
This will only run one AJAX call from the #myID element's click event handler at a time.

Its possible to kill the previous ajax or you can create an boolean with running, when someone click you set it to true and you have an if(!running){ //do ajax }, on the callback of the ajax you set the running to false

Use a synchronous AJAX call (The default is asynchronous). See this question for details on how to do that.

There are probably 100 better ways, but...
$("#myID").click(function() {
var is_running = $(this).data('running');
if (!is_running)
$(this).data('running', true);
else
return;
/* Do stuff */
$(this).data('running', false);
}

Use callbacks to ensure the order of execution.
$("#myID").click(function(){
$.ajax({
url: 'whatever url you are calling',
success: function(){
alert('ajax done');
$('whatever "it" is').fadeIn(300, function(){
//code place here will not execute until after fade in
alert('fadeIn done');
}
}
})
});

Related

wait for async call to finish before firing function in event listener

I am collaborating on a web project with someone who devised a series of .js scripts that act like 'plugins' in the sense that he would like them to be used on other web projects.
Most of these 'plugins' are event listener based, and they listen for clicks on elements with certain 'data' attributes. For example an element with 'data-setdata' will fire, on click, a listener in 'setdata.js':
$('body').on('click', '[data-setdata]', function(e) {
// do something
});
But one of these plugins, 'ajax.js', fires a 'post' call for AJAX-style loading of content:
$('body').on('click', '[data-ajax]', function(e) {
$.post(
//etc
);
}
});
...so of course we find ourselves in a situation in which we cannot control the order in wich 'setdata.js' and 'ajax.js' occur.
My initial thought was to get those plugins back into functions, and properly chain them using promises on a main .js
But, is there a way to delay firing the function within an event listener until a certain async action has been fulfilled? pseudocode:
$('body').on('click', '[data-setdata]', function(e) {
when( ajax call finishes ){
// do something
}
});
Thank you
You can use jQuery's ajaxComplete event
let done = false;
$(document).on("ajaxComplete", function(event, jqxhr, settings) {
if (settings.url === "/path/to/resource" && !done) done = true;
});
$('body').on('click', '[data-setdata]', function(e) {
if (done) {
// do something
} else {
console.log(done)
}
});
You should use ajax's complete option, which executes when the call is completed, no matter if it is successful or not.
$.ajax({
type: "GET",
....
success: function(data) {
// do some stuff
},
error: function(data) {
// do other stuff stuff
},
complete: function(data) {
// call your other function here
}
});
As explained in this answer: https://stackoverflow.com/a/22125915/5721273 I could use a setTimeout within the plugins, to continuously poll for changes on a flag set by the ajax call completion.
function checkFlag() {
if(flag == false) {
window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
} else {
/* do something*/
}
}
checkFlag();
Of course this is not the proper way of doing it, which would be chaining promises.
But in the specific case-scenario that I described, in which there is a design limitation imposed by someone else, and when I already told this person about it, but still need to find a temporary workaround, this is the correct answer.

Jquery Execute function After third party function ends

I didn't find any result for my issue.
I have Prestashop 1.5.6, I need to execute my jQuery function after blockcart adds the product.
BlockCart and my code starts with the same event, As I far know the unbind disables the other handlers event, how can I restart the unbind in the footer code?.
So my code don't work because Blockcart starts on first
//---------BlockCart Code---------
overrideButtonsInThePage : function(){
//for every 'add' buttons...
$('.ajax_add_to_cart_button').unbind('click').click(function(){
var idProduct = $(this).attr('rel').replace('nofollow', '').replace('ajax_id_product_', '');
if ($(this).attr('disabled') != 'disabled')
ajaxCart.add(idProduct, null, false, this);
return false;
});
//for product page 'add' button...
$('#add_to_cart input').unbind('click').click(function(){
ajaxCart.add( $('#product_page_product_id').val(), $('#idCombination').val(), true, null, $('#quantity_wanted').val(), null);
return false;
});
//-------- Footer code--------
$('.button.ajax_add_to_cart_button.exclusive, .button.ajax_add_to_cart_button.btn.btn-default').on('click',function(){
var id_product = $(this).attr('data-id-product');
myfunction(id_product);
});
It's possible to detect when blockcart ends the script without a editing the blockCart module with a callback function?
Thanks!
Finally the result was an override the blockCart function.
I did a copy of the overrideButtonsInThePage into my js to override it and I add my code inside the events.
Works perfectly
Depending on how blockcart functions, you can try:
//-------- Footer code--------
$('.button.ajax_add_to_cart_button.exclusive, .button.ajax_add_to_cart_button.btn.btn-default').click(function(){
var id_product = $(this).attr('data-id-product');
setTimeout(function() { myfunction(id_product); }, 0);
});
This will cause your function to execute after the existing stack finishes executing. You can learn more about what this does in Why is setTimeout(fn, 0) sometimes useful?. This will only be helpful if the blockcart handler is synchronous.
You can actually monitor ajax calls by using $.ajaxComplete(); and .ajaxStart()
http://api.jquery.com/ajaxcomplete/
What you can do is compare url the ajax is being sent to. Add to cart URL has GET parameters pre-encoded into it, so distinguishing it from other ajax calls isnt hard. Then on $.ajaxComplete(); you should compare the response result (determin that it was a succes) and then execute your function. This way you wont modify anything, you will just be observing the ajax actions

settimeout not working i dont know why

$('form[name=addform]').submit(function() {
if(error == true){
return false;
}else{
$('#loading').empty();
$('#loading').append("<img src = './images/ajax-loader.gif'/>");
$('#loading').show();
setTimeout(function(){
return true;
}, 4000);
}
error = false;
});
i need to load gif image before executes the return true. i do not use ajax for this please help
I'm not exactly sure what you are trying to accomplish, but that code won't work. setTimeout() does not pause the function it has been called from, nor does the return statement in the callback affect it.
JavaScript is asynchronous, not synchronous - setTimeout will not 'block' the execution of the next line of code. (See related What is the difference between synchronous and asynchronous programming (in node.js))
To submit the form after a delay (for what purpose is unclear) you will first need to stop the form submitting (by cancelling the event) then submit the form once again as when setTimeout callback is executed.
$('form').on('submit', function(event) {
// Prevent the form from submitting
event.preventDefault();
// 'this' is referring to the event target
var form = this;
// It may not be required to wrap the `form.submit` method but it's usually safer to do so
setTimeout(function() {
form.submit()
}, 4000);
});
Here is an example http://jsfiddle.net/xppNp/1/

Why does `$.post` works only if `alert()` presents after it?

I have the following javascript code:
$.post("<receiver>", postdata);
And gets postdata not always. If I write the following code all works good:
$.post("<receiver>", postdata);
alert('bla-bla-bla, read me for a second');
Why? The page is changing on the save button as the javascript runs. But I need to send post data before redirecting.
You should redirect inside the success callback of your AJAX call:
$.post("<receiver>", postdata, function() {
window.location.href = '...';
});
The reason why your code works if you put an alert immediately after the $.post call is because when this alert pops up, the browser suspends the execution and your AJAX call has enough time to complete.
Don't forget that the first A in AJAX stands for Asynchronous meaning that you could only consume the results returned from the server inside the success callback.
Also if this AJAX call is performed inside some .submit() event handler of a form or inside some .onclick() handler of a submit button or an anchor you should make sure that you have canceled the default action by returning false otherwise your AJAX call will never have the time to execute before the browser redirects away from the page.
Example:
$('#myForm').submit({
$.post("<receiver>", postdata, function() {
...
});
return false; // <!-- That's the important bit
});
Ah, so it seems that the missing portion of your question is you are sending data on click of something yes? Presumably a link? That link causes the browser to follow it immediately, and in your example the alert is delaying the browser enough that your post has enough time to complete.
You need to ensure that the default action of that link is blocked, and do the redirect in the callback of your $.post() instead:
$("a.some_class").click(function(evt)
{
evt.preventDefault(); // makes sure browser doesn't follow the link
// gather your post data here ...
var $this = this;
$.post("<receiver>", postdata, function()
{
window.location.href = $this.attr("href");
});
})
Your alert is causing your script to pause and therefore allowing time for your $.post() to complete.
You should put your redirect script in your $.post() callback.
because it causes a delay. While you press OK the request (which takes at least a few milliseconds) gets finished and the stuff depending on it can follow.
To prevent this, you can pass a callback function that runs after the request got its response.
$.post( url, postdata, function() {
// Success.
} )
The .post is asynchronous.
If you change page during the post process () the POST request will get aborted.
Your alert is preventing this page change
You should replace your .post with a .ajax synchronous request, validating form submission on success ( return true; ) . Or do as suggested by #DarinDimitrov or #Curt

$(window).unload not working as expected

I'm making a small chat application with PHP + MySQL + JavaScript, I've written a function disonnectUser(), which is called when the user press the disconnect button. Here it is:
function disconnectUser(){
$.post('web/WEB-INF/classes/handleChatUser.php',{ action: 'disconnect',nick: localNickname});
$('#chat').stop(true,true).fadeOut(2000,function(){
nicknameDialog();
});
$('#messageInput').val(null);
$('#clientList').html(null);
$('#chatScreen').html(null);
clearInterval(refreshIntervalId);
clearInterval(refreshIntervalId2);
connected = false;
}
And it works like a charm, but when I call this very function in another context, when the user instead of pressing disconnect just exit the page, in this function
$(window).unload(function() {
if(connected){
disconnectUser();
connected = false;
}
});
it doesn't work. And I'm sure it's being called, because if I put an alert it's called normally before closing the page. I think the page is closing before the code runs completely, so I think if I put some block there until the code finish running it would work?
The problem is that $(window).unload() doesn't waits any AJAX call before closing the window (what is right because AJAX is assync).
You need to force the AJAX to be sync, ie, wait the response. Inside your disconnectUser function:
$.ajax({
type: 'POST',
async: false, // This is the guy.
url: '/blablabla'
});
You can read more about it here: $(window).unload wait for AJAX call to finish before leaving a webpage
Instead of unload, how about beforeunload?
window.onbeforeunload = function() {
if(connected){
disconnectUser();
connected = false;
}
};
Also, your disconnectUser method already sets connected to false, no need to do it here also.
It also seems that jQuery doesn't really handle the beforeunload event, which is why you'll need to revert to native JS to handle this:
http://groups.google.com/group/jquery-en/browse_thread/thread/4e5b25fa1ff5e5ee?pli=1
Try using a synchronous request. Perhaps in combination with onbeforunload like the other poster suggested. If that doesn't work, I suppose you're out of luck. A request that is synchronous blocks the browser while it's happening, so you might want to use it only for the unload function, assuming the method even works.
function disconnectUser(){
jQuery.ajax({
url: 'web/WEB-INF/classes/handleChatUser.php',
data: { action: 'disconnect',nick: localNickname},
type: 'POST',
async: false
});
$('#chat').stop(true,true).fadeOut(2000,function(){
nicknameDialog();
});
$('#messageInput').val(null);
$('#clientList').html(null);
$('#chatScreen').html(null);
clearInterval(refreshIntervalId);
clearInterval(refreshIntervalId2);
connected = false;
}

Categories