Is there any way to check if the event is completed and element is free to perform another action?
Like I want to do
$('#button-cancel').on('click', function() {
// send ajax call
});
/****************************************
extra code
*******************************************/
$('#button-cancel').on('click', function() {
if(ajax call is completed) {
//do some thing
}
});
I don't want to send ajax call in second onclick as it is already been sent, just want to check if it is done with ajax then do this
You can introduce a helper variable:
// introduce variable
var wasAjaxRun = false;
$('#button-cancel').on('click', function() {
// in ajax complete event you change the value of variable:
$.ajax({
url: "yoururl"
// other parameters
}).done(function() {
// your other handling logic
wasAjaxRun = true;
});
});
$('#button-cancel').on('click', function() {
if(wasAjaxRun === true) {
//do some thing
}
});
EDIT: I just noticed that you have event handlers attached to the same button. In that case my initial answer would not work, because first event hander would be executed every time you click the button.
It is not very clear from the description what you want to do with your first event hander. I assume you want to use some data, and if you already have this data, then you use it immediately (like in second handler), if you don't have it - you make the AJAX call to get the data (like in first handler).
For such scenario you could use single event handler with some conditions:
var isAjaxRunning = false; // true only if AJAX call is in progress
var dataYouNeed; // stores the data that you need
$('#button-cancel').on('click', function() {
if(isAjaxRunning){
return; // if AJAX is in progress there is nothing we can do
}
// check if you already have the data, this assumes you data cannot be falsey
if(dataYouNeed){
// You already have the data
// perform the logic you had in your second event handler
}
else { // no data, you need to get it using AJAX
isAjaxRunning = true; // set the flag to prevent multiple AJAX calls
$.ajax({
url: "yoururl"
}).done(function(result) {
dataYouNeed = result;
}).always(function(){
isAjaxRunning = false;
});
}
});
You should be able to provide handlers for AJAX return codes. e.g
$.ajax({
type: "post", url: "/SomeController/SomeAction",
success: function (data, text) {
//...
},
error: function (request, status, error) {
alert(request.responseText);
}
});
you can disable the button as soon as it enters in to the event and enable it back in ajax success or error method
$('#button-cancel').on('click', function() {
// Disable button
if(ajax call is completed) {
//do some thing
//enable it back
}
});
This is edited, more complete version of dotnetums's answer, which looks like will only work once..
// introduce variable
var ajaxIsRunning = false;
$('#button').on('click', function() {
// check state of variable, if running quit.
if(ajaxIsRunning) return al("please wait, ajax is running..");
// Else mark it to true
ajaxIsRunning = true;
// in ajax complete event you change the value of variable:
$.ajax({
url: "yoururl"
}).done(function() {
// Set it back to false so the button can be used again
ajaxIsRunning = false;
});
});
You just need to set a flag that indicates ajax call is underway, then clear it when ajax call returns.
var ajaxProcessing = false;
$('#button-cancel').on('click', function(){
processAjaxCall();
});
function processAjaxCall() {
if(ajaxProcessing) return;
ajaxProcessing = true; //set the flag
$.ajax({
url: 'http://stackoverflow.com/questions/36506931/javascript-how-to-check-if-operation-has-been-completed-on-this-event'
})
.done(function(resp){
//do something
alert('success');
})
.fail(function(){
//handle error
alert('error');
})
.always(function(){
ajaxprocessing = false; //clear the flag
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button-cancel">Cancel</button>
What you can do is call a function at the end of an if statement like
if(ajax call is completed) {
checkDone();
}
function checkDone() {
alert("Done");
}
Related
In the below code I am making an API call to my backend node.js app using setTimeout() which calls my AJAX at every 5 seconds. Inside my AJAX success I am displaying divContent1 & divContent2 based on certain condition which should execute at least once. After that only divContent2 should be visible at each setTimeout() calls.
index.html
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
url: "http://localhost:8070/api/route1",
type: 'POST',
dataType:'json',
success: function(res) {
//Some Task
}
});
$("#myButton").click(function(){
const route2 = function() {
$.ajax({
url: "http://localhost:8070/api/route2",
type: "POST",
dataType: "json",
data: { var1: val1 },
success: function (res) {
// Various tasks
if(res.flag){
$("#divContent1").hide();
$("#divContent2").show();
}
else{
$("#divContent1").show();
}
//Functions that handle div content data
},
beforeSend: function() {
$("#divContent1").hide();
$("#divContent2").hide();
},
complete: function() {
setTimeout(route2,5000);
},
});
};
$(function(){
route2();
})
});
});
</script>
The setTimeout() calls the entire route2 function which handles all the display and insertion of div content. However, the ask is to only display divContent2 from the second call.
Looking for a solution for this
The setTimeout() calls the entire route2 function which handles all
the display and insertion of div content. However, the ask is to only
display divContent2 from the second call.
You're calling route2 recursively with setTimeout(route2,5000); under complete. So this will run infinitely as complete occur each time an ajax call is completed (wether success or error). So what you can do is to create a timer and clear it after the second execution, something like this:
var ctr = 0, timer =0;
const route2 = function() {
$.ajax({
...
success: function (res) {
//Write you logic based on ctr
}
complete: function() {
if(ctr>0){
clearTimeout(timer)
}else{
timer = setTimeout(route2,5000);
ctr = ctr+ 1;
}
},
});
};
Will an external variable be enough? Just define it in the outer context and set/check it to choose the behavior:
// before declaring button click handler
var requestDoneAtLeastOnce = false;
// ...
// somewhere in success handler
success: function (res) {
if (!requestDoneAtLeastOnce) {
requestDoneAtLeastOnce = true;
// do something that belongs only to handling the first response
}
else {
// this is at least the second request, the other set of commands belongs here
}
}
In order to prevent getting an error twice I use beforeSend.
hasSent = false
function submit() {
if (!hasSent)
$.ajax({
url: "${createLink(controller:'userInvitation', action:'ajaxUpdate')}",
type: "POST",
data: $("#invitationForm").serialize(),
success: function(data, textStatus, jqXHR) {
$('#invitationForm')[0].reset();
$('.thank-you-modal').modal('show');
hasSent = true;
console.log(hasSent)
},
complete: function() {
hasSent = false;
console.log(hasSent)
}
});
}
As you can see the ajax should happen only if hasSent=false.
For some reason the ajax happens also if the user clicks multiple time (very quick) on the submit button
To prevent this kind of issue disable the button before sending the ajax and then anable inside the success function
$(mybutton).prop("disabled",true);
// ajax call here
then
success: function(data, textStatus, jqXHR) {
$(mybutton).prop("disabled",false);
// code here
}
You can create another flag such as isSending
function submit() {
if(isSending)
return;
isSending = true
$.ajax({
// ...
complete: function() {
isSending = false;
}
});
}
there are two ways you can do this.
1) create a flag and check if the button is pressed. If pressed then do not execute the ajax code
change the flag back once the request is successful, like this
success:function(...)
{
flag=false;
}
Or you can disable the button at the button click so the request will be carried out and double click situation won't arise. Enable the button on complete like this
complete:function(..){ $("yourbutton").attr("disabled",false)}
Here is the scenario:
I am sending ajax request when user click on anchor tag to fecht & update instagram media status.
But it take sometime to retrieve the response, in that time user clicked N number of time on that anchor tag.
So each time it sends the request, I am don't want such behaviour ..
Is there any easy way to handle such situation?
Currently I am adding the class when user clicked on it, and using that I am deciding user has click on anchor tag or not??
Please let me know, if it is correct way or not..
Here is fiddle URL (Not clicked on link at least 2+ times, it send 2+ request which is i don't want )
http://jsfiddle.net/bkvaiude/mxb8x/
thanks
You should use should remove the click event and then set it up again when the ajax call is complete:
Instead of setting it in the success call as the others do; you should use the complete callback to set it. To make sure if the server returns an error it is still binding the click event again.
http://jsfiddle.net/eWwZt/
(function (){
console.log("bhushan");
var ajaxCall = function(e){
$("#test").off("click");
console.log("click");
e.preventDefault();
var is_liked_url = "https://api.instagram.com/v1/media/popular?client_id= b52e0c281e584212be37a59ec77b28d6";
$.ajax({
method: "GET",
url: is_liked_url,
dataType: "jsonp",
success: function(data) {
console.log("data...");
},
complete: function(){
$("#test").on("click", ajaxCall);
}
});
}
$("#test").on("click", ajaxCall);
})();
Put a flag to check if ajax call completed or not this way:
(function (){
var RequestInProgress = false;
console.log("bhushan");
$("#test").on("click", function(e){
e.preventDefault();
if(!RequestInProgress) // if request not in progress send
{
RequestInProgress = true;
var is_liked_url = "https://api.instagram.com/v1/media/popular?client_id= b52e0c281e584212be37a59ec77b28d6";
$.ajax({
method: "GET",
url: is_liked_url,
dataType: "jsonp",
success: function(data) {
console.log("data...");
RequestInProgress = false;
}
});
}
});
})();
UPDATED FIDDLE
You can use .off() to unbind click to element.
(function () {
console.log("bhushan");
var Myfunction = function (e) {
$("#test").off("click"); //Unbind click
e.preventDefault();
var is_liked_url = "https://api.instagram.com/v1/media/popular?client_id= b52e0c281e584212be37a59ec77b28d6";
$.ajax({
method: "GET",
url: is_liked_url,
dataType: "jsonp",
success: function (data) {
console.log("data...");
$("#test").on("click", Myfunction);
}
});
};
$("#test").on("click", Myfunction);
})();
DEMO
try this
var gettingData =false;
$('selector').click(function() {
gettingData = false;
if (!gettingData) {
gettingData =true;
$.ajax(//do ajax logic)
.success(
gettingData = false;
//parse data)
.error(
gettingData = false;
//display some error
);
} else {
return false;
}
});
The HTML code: <input id="goTOxQuestion">
The js code:
$("#goTOxQuestion").keyup(function(){
// send a XHR
})
If the input is 12345,it will send the XHR five times.In fact, I only want the XHR be executed when I have completed the input. I mean,there is no input( no keydown event )in 500 milliseconds, rather then it loses faocus.
My incomplete solution:
var isOver = false;
$("#goTOxQuestion").keyup(function(){
//...
setTimeout(function(){
if(isOver){
//send a XHR
}
},500);
})
$("#goTOxQuestion").keydown(function(){
isOver = false;
})
You can use a combination of setTimeout and clearTimeout like this:
var hTimeout;
$("#goTOxQuestion").keyup(function () {
if (hTimeout) {
clearTimeout(hTimeout);
}
hTimeout = setTimeout(function () {
// ajax code here
}, 500);
});
Demo here
Note that the order in which AJAX requests complete is not guaranteed and you will end up with "race conditions".
Regarding your comment, here is a solution from the top of my mind:
// initialize global counter
var xhrCount = 0;
// increment counter when you create an XHR
xhrCount++;
// pass the current value of this
// variable to the success function
// http://stackoverflow.com/q/1552941/87015
$.ajax("/url/", (function (myStamp) {
console.log("creating success callback #" + myStamp);
return function () {
if (myStamp === xhrCount) {
console.log("firing success handler");
} else {
console.log("suppressing success handler");
}
}
})(xhrCount));
Use setTimeout then:
$("#goTOxQuestion").keyup(function(){
setTimeout(function(){
// send a XHR
}, 1000);
})
The change event seems like a good fit for your needs :
$("#goTOxQuestion").change(function(){
// send a XHR
})
It will be triggered when the input looses focus and the input value was actually modified.
$(document).on('blur',"#goTOxQuestion",function(){
// send a XHR
});
I have some image buttons that have jQuery event handlers attached to them.
I want to make an AJAX call in the click() event to determine if the action should actually be allowed. Because I am doing an async ajax call I have to return 'false' to immediately cancel the event and wait for the response.
$('[id^=btnShoppingCartStep_]').click(function() {
var stepName = this.id.substring("btnShoppingCartStep_".length);
$.ajax({
type: "POST",
url: $.url("isActionAllowed"),
data: "requestedStep=" + stepName,
dataType: "json",
success: function(data) {
if (data.allowed) {
// need to resume the action here
}
else {
AlertDialog(data.message, "Not allowed!");
}
}
});
return false;
});
I need to find the best way to resume the click event if the AJAX call determines that it should be allowed.
Any way of doing this that I can come up with seems clumsy, such as :
1) remove event handler from the buttons
2) simulate a click on the button that was clicked
Is there any nice way of doing this that I'm missing?
How long does it take to confirm the validity of the request? What else would be the user be doing during that time?
Why not have the server do the validation? Is that too risky? You could simply pass the data along to the server, have it determine if it's valid. If it's not, it tells Ajax "not allowed", the function alerts the user. If it liked the data, there is no need to resume the action as it's already done.
if you need submit form:
$('#form_id').submit();
if you need continue this function:
var allowed_actions = {};
$('[id^=btnShoppingCartStep_]').click(function() {
var stepName = this.id.substring("btnShoppingCartStep_".length);
var $click_me_again = $(this);
if (!allowed_actions[stepName]) {
$.ajax({
type: "POST",
url: $.url("isActionAllowed"),
data: "requestedStep=" + stepName,
dataType: "json",
success: function(data) {
if (data.allowed) {
// need to resume the action here
allowed_actions[stepName] = true;
$click_me_again.click();
}
else {
AlertDialog(data.message, "Not allowed!");
}
}
});
return false;
} // end if
// continue function (check passed)
});
Assign an ID to your form. Let's say you name it myForm. Where your // need to resume the action here is, use this:
$("#myForm").trigger("submit");
1) Simply call the form's submit() method.
$("#FormID").submit();
2) Also, if what you want is to intercept form submissions for that for, you may want to do this slightly differently (e.g. if you can submit the form via >1 button):
$("form").submit(function() {
...