Executing my code during when ajax is in progress - javascript

Given my below code Is there a way i can get alert when my ajax process is still in progress?
as you have already noticed code for alert will never get executed because of obvious reason that async ajax will keep happening but the value of click false will come before that and i will never be able to get alert during ajax call. Is there any way i can get alert when ajax request still in process?
<html>
<body>
<button type="button" id="submit-catalog" class="btn btn-primary">Activate</button>
</body>
</html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
var clicked = false;
$(document).on('click', '#submit-catalog', function() {
clicked = true;
//doing some ajax call which is taking time
});
if(clicked){ // never get executed
alert("button clicked")
//i am executing some function only if that button clicked
}
});
</script>

Your logic is off; here's how to do this:
var clicked;
$(document).ready(function() {
$(document).on('click', '#submit-catalog', function() {
if (clicked) {
console.log("ajax still in progress");
return false;
}
clicked = true;
console.log("starting ajax");
setTimeout(function () {
clicked = false;
console.log("ajax done");
}, 3000);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="submit-catalog" class="btn btn-primary">Activate</button>
I'm not sure if this is what you're looking for, but this will prevent the ajax from firing again and again based on the variable which keeps track of the ajax progress.

It's not about Ajax. Code is getting executed top to bottom, you declared event listener on the document and it waits for action, while your 'if' statement was already processed.
This 'Alert' or any other action should be done within event listener
Also, if you want to do any action before executing ajax request you simply use beforeSend: ()=>{/*your actions*/}, and then after ajax request is done success: callback=>{/*do when done*/}
which may look like that:
$.ajax({
url: url,
method: 'POST',
beforeSend: ()=> { alert('clicked') },
success: callback=> { console.log(callback) }
})

You can also use : one() instead of on() only if you don't use the clicked variable somewhere else. You attach the event for only one trigger. At the end of the callback you reattach it.
$(document).ready(function() {
function foo(e){
setTimeout(function () {
console.log("ajax done");
$(e.delegateTarget).one('click', '#submit-catalog', foo)
},1000)
}
$(document).one('click', '#submit-catalog', foo);
});
Other solution : add class to stop the propagation thanks to delegate event
$(document).ready(function() {
$(document)
.on('click', '#submit-catalog.prevent', function(e){
e.stopImmediatePropagation();
}
.on('click', '#submit-catalog', function(){
$(e.currentTarget).addClass('prevent');
setTimeout(function () {
console.log("ajax done");
$(e.currentTarget).removeClass('prevent');
}, 1000)
});
});

Related

How to trigger another jquery event using the return data of previously executed jquery event

I have a button, for example
<a id="btn" class="button">Submit</a>
When this button is clicked, it triggers a jquery function
for example,
$("#btn").on("click", function() {
$.ajax({
url: 'index.php',
type: 'post',
data: {product_id: 1, qty: 2},
dataType: 'json',
success: function(json) {
if (json['success']) {
console.log('Product added to cart');
}
if (json['error']) {
console.log('Product not added to cart');
}
});
});
Now, I would like to know if it is possible to trigger another jquery event by some other jquery code, once the above function is executed, and I want to use the return values of the previous function without making any changes to the above-mentioned function.
For example, I would like to run the following function immediately after the above jquery event by writing another jquery code and not changing any part of the previous code.
function anotherAction(json_array) {
if (json_array['success']){
//calling another function
}
}
You mean
function anotherAction() {
if (submitBtn() == 'Submitted'){
console.log('Button is submitted');
}
}
But then you need to make str global in scope
Perhaps like this
let str;
$("#btn").on("click", function() {
str = 'Submitted';
});
$("#check").on("click", anotherAction);
function anotherAction() {
console.log('Button has '+(str === 'Submitted' ? "" : "not ")+'been clicked');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="btn" type="button">Click</button>
<button id="check" type="button">Check</button>
without making any changes to the above-mentioned function.
No. Its not possible. submitBtn function's return value is unused/no-reference/destroyed inside "#btn" click event. So you'll never know what was returned.

Handling multithreadiing issue in javascript/jquery?

$(".getDetails").click(function() {
// some stuff like fetching response from server
})
when user clicks getDetails button on UI multiple times within fraction of second , jquery generates two calls for click function and my logic fails.
I think solution to this will be to disable the button on first click itself(so that use can't click multiple times). Once i get the response or just before returning
from click method i make it enable. Is there any better solution ?
If no, how can i make button disable as soon as user click button first time. I think it needs to be done before calling click method or some where in html element ?
Java provides synchronized keyword so that only one thread enters at time inside method , i am not sure is similar thing exist in javascript or not ?
Assuming the click handler executes an AJAX request you can set the button as disabled before making the request, then enable it again once the request completes. Try this:
$(".getDetails").click(function(){}
var $btn = $(this).prop('disabled', true);
$.ajax({
url: '/foo'
success: function() {
console.log('It worked!');
},
error: function() {
console.log('It failed!');
},
complete: function() {
$btn.prop('disabled', false);
}
});
});
you can try unbinding click event and after ajax call again bind click to that class
$(".getDetails").click(function(){}
$(".getDetails").unbind('click');
// some stuff like fetching response from server
)
You can use simple flag to prevent firing your logic multiple times:
var flag = true
$(".getDetails").click(function() {
if (flag) {
flag = false;
//your logic...
//when your code ends (in after-AJAX callback for example)
flag = true;
}
});
$(".getDetails").click(function(e){
var $target = $(e.currentTarget);
// assuming the click listener is on the button
$target.prop('disabled',true);
// request, stuff...and when done:
$target.prop('disabled',false);
})
try Prevent Default and return false to avoid any other event propagation
This is solution is like semaphore or monitor
var progress = false;
$(".getDetails").on('click', function(e) {
if(!progress){
progress = true;
// some stuff like fetching response from server
//also after sucessfull fetch make true to false again
}else{
console.log('something in progress');
}
e.preventDefault();
return false;
})
This should make sure that your button will not fire the async request twice, until you have a response.
function doAjaxReq() {
/*
Add your ajax operation here
as a return value of doAjaxReq
like so:
return $.ajax({
url: '/foo',
type: 'POST',
data: data
})
Since i can't use ajax here let's smilulate
it useing a promise.
*/
promise = new Promise(function(res, rej) {
setTimeout(function(){
res({foo: "bar"});
}, 1000)
})
return promise;
}
/*
Inside here you add the click handlder
only once use `elem.one('click'...`
*/
function addClickHandler(elem) {
elem.one('click', function() {
// do your ajax request and when its
// done run `addClickHanlder` again
// i'm using `.then` because of the promise,
// you should be using `.done`.
doAjaxReq().then(function(data) {
console.log(data);
addClickHandler(elem);
});
})
}
addClickHandler($(".getDetails"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="getDetails">Get Details</button>

AJAX returns data only after first click

I have this ajax request script:
function SendData(){
$( "#Submit" ).click(function() {
$('#Submit').attr("disabled", true);
$.ajax({
type:"POST",
url:"assets/process.php",
data: {
Years : $('#Years').val()
},
success: function(Response){
if (Response.Status == 'Error') {
swal("Ups!", "Nemo' zebavaš", "error");
} else if (Response.Status == 'Error0') {
swal("Ups!", "Servis 'Misterije' mogu koristiti samo rođene osobe!", "error");
}
else if (Response.Status == 'Error120') {
swal("Ups!", "Žao nam je! Niste podobni za korišćenje WEB Servisa 'Misterije'!", "error");
}
else if (Response.Status == 'Success') {
swal("USPEŠNO!", 'Rođeni ste: '+Response.Calculated+' godine!', "success");
}
$('#Submit').attr("disabled", false);
}
});
});
}
When I load page in browser, add data to input and click on button nothing happens, but on second and all clicks after until I refresh page all working OK.
How I can slove this problem?
Don't call the function
Put your code in $(document).ready function
Presumably you're calling this SendData() function when you click the button?
This function isn't doing what you think it's doing. It's not invoking the AJAX request. All this function does is attach the click handler to the button. Nothing more. Then the next time you click the button, that handler will execute.
(Not to mention that it would also again attach another click handler. So the third click would invoke the handler twice. And so on...)
There's no need to wrap all of this in a function. Instead of this:
function SendData(){
$( "#Submit" ).click(function() {
// your code
});
}
just do this:
$( "#Submit" ).click(function() {
// your code
});
This will attach the click handler, not invoke it. Any time afterward when you click the button the handler will be invoked.
At worst, you'd have to do this if the button doesn't exist yet when this code executes:
$(function () {
$( "#Submit" ).click(function() {
// your code
});
});
This would wait until the document.ready event and then attach the handler.
(Note: You'll also want to remove any reference to SendData() once you've removed that function. I'm assuming you're calling it in-line from the button. But you don't need to do that when you're attaching a click handler with jQuery.)

JQuery Prevent Function .click Firing On Every Click

When I click a chat on my site I want the messages to be grabbed from the server so I use an $.post request like so :
$("#friendsDiv").on("click", "#aFriend", function(event){
retrieveMessages();
}
and this is what is in the retrieveMessages function
$.post("PHP/chat.php",
{
action:'retrieveMessages',
last_message: last_message,
conversation_id:conversation_id
},
function(data){
$("#messages").append(data);
last_message = $("#messages").find(".aMessage:last").attr("id");
$("#messages").animate({ scrollTop: $("#messages")[0].scrollHeight}, 1000);
}
);
The issue is that if the button is clicked very quickly multiple post requests will begin before the last_message is updated, this results in many copies of the same messages being displayed. Is there a way to prevent the button being clicked quickly or stop the post request being processed if another of the same request is already being processed?
EDIT
The #aFreind element is a DIV not a button
Typically in such situation you just disable a button until request is complete. For this you will need to provide a callback function. For example:
$("#friendsDiv").on("click", "#aFriend", function (event) {
// reference the button
var button = this;
// disable the button
this.disabled = true;
// provide a callback to be invoked when post is done
retrieveMessages(function() {
button.disabled = false;
});
});
function retrieveMessages(callback) {
$.post("PHP/chat.php", {
action: 'retrieveMessages',
last_message: last_message,
conversation_id: conversation_id
}, function (data) {
$("#messages").append(data);
last_message = $("#messages").find(".aMessage:last").attr("id");
$("#messages").animate({
scrollTop: $("#messages")[0].scrollHeight
}, 1000);
// execute callback which enables button again
callback();
});
}
Demo: http://jsfiddle.net/9t8fLdjn/
Your best bet would be to disable the button and then enable it after $.post
$("#friendsDiv").on("click", "#aFriend", function(event) {
$(this).prop('disabled', true); // disable
retrieveMessages();
});
and the retrieveMessage function
$.post("PHP/chat.php", {
action: 'retrieveMessages',
last_message: last_message,
conversation_id: conversation_id
}, function(data) {
$("#messages").append(data);
last_message = $("#messages").find(".aMessage:last").attr("id");
$("#messages").animate({
scrollTop: $("#messages")[0].scrollHeight
}, 1000);
$(this).prop('disabled', false); // enable it again
});
Instead of using on you could use the one jQuery function and bind the button again in the callback. Se http://api.jquery.com/one/
$("#friendsDiv").one("click", "#aFriend", retrieveMessages });
var retrieveMessages = function(){
$.post("PHP/chat.php", {
...
}).done(function(){
$("#friendsDiv").one("click", "#aFriend", retrieveMessages });
});
};

On click myFunction and wait until it is finished

I thought this is something easy to do but I dont find anything helping me out of this.
I have a function
(function($){
myFunction = function(e){
e.preventDefault();
// do stuff
// load ajax content
// animate and show
}
$('.button').on( 'click', myFunction);
})(jQuery);
now this works but I need to know, wait untill everything is done if someone presses many .buttons in a short time cause there are a few elements with class button
I've tried with promise()
$('.button').on( 'click', function(){
$.when( myFunction() ).done(function() {
alert('finished')
});
});
but that gives me an error e is undefined and
$('.button').on( 'click', myFunction).promise().done(function() {
alert('finisehd');
});
anyone knowing what I'm doing wrong and how I could do it to get it to work?
The most common solution would be to set a variable inside the click handler when myFunction is called and check its state with every call of the click handler.
This could be done somewhere along the lines of this:
(function($){
var wait = false;
myFunction = function(e){
e.preventDefault();
if (wait) {
return;
}
wait = true;
// ...
wait = false;
}
$('.button').on( 'click', myFunction);
})(jQuery);
Your function myFunction expects one argument, when you call myFunction() the argument is missing.
Not tested but it should works:
$('.button').on( 'click', function(e){
$.when( myFunction(e) ).done(function() {
alert('finished')
});
});
In addition to not passing in the e variable. You're using $.when incorrectly.
If you want to have the done function called after myFunction finishes its ajax call. You'll need to return a promise from myFunction.
function myFunction(e) {
return $.Deferred(function(deferred) {
doAjax(function(content) { // callback
deferred.resolve(content);
});
});
}
Now when you do
// inside event handler
$.when(myFunction(e)).done(function(content) {
// whoo!
});

Categories

Resources