4
$(".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 ?

3
  • What logic is being performed in the click handler? I assume it's an AJAX request Commented Aug 2, 2016 at 8:15
  • 2
    Yes. You should disable the button on first click to prevent successive clicks. Commented Aug 2, 2016 at 8:17
  • @james agin my question is at what point of time i need to do it and where i need to do it. Can you provide some example ? Commented Aug 2, 2016 at 8:22

6 Answers 6

2

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);
        }
    });
});
Sign up to request clarification or add additional context in comments.

11 Comments

But in this case also there is a probability two thread enters at same time inside click method and then both will proceed. Right ?
JS is only single threaded so that issue is moot. However this would avoid the problem of quick successive clicks firing the the event handler multiple times before the first AJAX request completes.
Sorry I did not get what do you mean by JS is single threaded ? Does it mean second thread can not enter the method till first thread completes. If yes i should not have faced the issue. Is n't it ?
Js only operates on a single thread. It runs on an event based system - this is what caused your issue. One event was still in process while another was raised. That is the problem that this answer solves.
No, multiple events can run at the same time. You seem a little confused about how threads work. I would suggest researching that - although it's not directly related to JS.
|
0

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
 )

Comments

0

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;
  }

});

4 Comments

But in this case also there is a probability two thread gets the value as true at same time and both send the request
@freedomn-m Sorry I did not get the statement There's no such thing as "two threads" in js ?Does it mean second thread can not enter the method till first thread completes. If yes i should not have faced the issue. . Right ?
No, I meant that javascript is single-threaded. There is only one thread. Only one "bit" of javascript can be running at a time - so, yes, your method must exit before it can start again... except if you run something that says "run this later", eg setTimeout or $.ajax (and derivatives)
@user3198603 I think it might be helpful for you to read some articles about multi-threaded code and asynchronous code in order to know what's the difference.
0
$(".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);
})

Comments

0

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;

})

Comments

0

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.