mauriblint
mauriblint

Reputation: 1707

Ajax, prevent multiple request on click

I'm trying to prevent multiple requests when user click on login or register button. This is my code, but it doesn't work. Just the first time works fine, then return false..

$('#do-login').click(function(e) {
    e.preventDefault();

    if ( $(this).data('requestRunning') ) {
        return;
    }

    $(this).data('requestRunning', true);

    $.ajax({
        type: "POST",
        url: "/php/auth/login.php",
        data: $("#login-form").serialize(),
        success: function(msg) {
            //stuffs
        },
        complete: function() {
            $(this).data('requestRunning', false);
        }
    });      
}); 

Any ideas? Thanks!

Upvotes: 42

Views: 95091

Answers (10)

Tayyab Hayat
Tayyab Hayat

Reputation: 933

I've tried this and worked very fine for me, I was having trouble that $.ajax send more request until results return,

 var settings = {
    "url": "/php/auth/login.php",
    "method": "POST",
    "timeout": 0,
    "async": false,
    "headers": {
        "Content-Type": "application/json; charset=utf-8"
    },
    "data": jsondata, //data pass here is in JSON format
};
$.ajax(settings).done(function (ress) {
  try{
      console.log(ress, "Result from Ajax here");
    }
    catch(error){
      alert(error);
      console.log(ress);
    }
});

async : false worked for me. Thanks.

Upvotes: 2

Atequer Rahman
Atequer Rahman

Reputation: 1219

I have also faced a similar problem.

Just adding $('#do-login').attr("disabled", true); gives me the solution.

$('#do-login').click(function(e) {
   e.preventDefault();
   $('#do-login').attr("disabled", true);
   .........
   .........

Here do-login is button id.

Upvotes: 3

Mohamad Hamouday
Mohamad Hamouday

Reputation: 2753

This function can help you with control multi Ajax requests and it's has timeout function which can return flag status to 0 after ex. 10sec (In case the server took more than 10 seconds to respond)

var Request_Controller = function(Request_Name = '', Reactivate_Timeout = 10000)
{
    var a = this;
    a.Start_Request = function(){
        if(window.Requests == undefined){
            window.Requests = {};
        }
        window.Requests[Request_Name] = {'Status' : 1, 'Time': + new Date()};
    }

    a.End_Request = function(){
        if(window.Requests == undefined){
            window.Requests = [];
        }
        window.Requests[Request_Name] = undefined;
    }

    a.Is_Request_Running = function(){
        if(window.Requests == undefined || window.Requests[Request_Name] == undefined){
            return 0;
        }else{
            var Time = + new Date();
            // Reactivate the request flag if server take more than 10 sec to respond
            if(window.Requests[Request_Name]['Time'] < (Time - Reactivate_Timeout)) 
            {
                return 0;
            }else{
                return 1
            }
        }
    }
}

To use it:

var Request_Flag = new Request_Controller('Your_Request_Name');
if(!Request_Flag.Is_Request_Running()){

    Request_Flag.Start_Request();

    $.ajax({
        type: "POST",
        url: "/php/auth/login.php",
        data: $("#login-form").serialize(),
        success: function(msg) {
            //stuffs
        },
        complete: function() {
            Request_Flag.End_Request();
        }
    }); 
}

Upvotes: 0

Musa
Musa

Reputation: 97672

In your ajax callbacks the context (this) changes from the outer function, you can set it to be the same by using the context property in $.ajax

$.ajax({
    type: "POST",
    url: "/php/auth/login.php",
    data: $("#login-form").serialize(),
    context: this, //<-----
    success: function(msg) {
        //stuffs
    },
    complete: function() {
        $(this).data('requestRunning', false);
    }
});      

Upvotes: 6

Paul Schwarz
Paul Schwarz

Reputation: 1958

I found the approach useful. I've implemented it as a general purpose function for jQuery with ES6.

export default function (button, promise) {
    const $button = $(button);
    const semaphore = 'requestRunning';

    if ($button.data(semaphore)) return null;
    $button.data(semaphore, true);

    return promise().always(() => {
        $button.data(semaphore, false);
    });
}

Because $.ajax() returns a promise, you simply pass in the promise and the function takes care of the rest.

Roughly speaking, here's the usage.

import preventDoubleClick from './preventdoubleclick';

...

button.click(() => {
    preventDoubleClick(this, () => $.ajax()
        .done(() => { console.log("success") }));
});

Upvotes: 0

user3300782
user3300782

Reputation: 1

for prevent multiple ajax request in whole site. For example: If use ajax request in other ajax page, Using ajax in php loop, etc, Give you multiple ajax request with one result. I have solution:

Use window.onload = function() { ...  } 

instead of

$(document).ready(function(){ ...  });

on the main index.php page. Its will be prevent all multi request. :)

Upvotes: -9

Oskar
Oskar

Reputation: 2562

Or you can do it by $(this).addClass("disabled"); to you button or link and after click is performed, you can $(this).removeClass("disabled");.

// CSS

.disabled{
cursor: not-allowed;

}

// JQUERY

$('#do-login').click(function(e) {
   e.preventDefault();

    $(this).addClass("disabled");
    $.ajax({
        type: "POST",
        url: "/php/auth/login.php",
        data: $("#login-form").serialize(),
        context: this,
        success: function(msg) {
    //do more here

           $(this).removeClass("disabled");
        },
    });
});

P.S. If you use bootstrap css, you do not need the css part.

Upvotes: 0

adeneo
adeneo

Reputation: 318182

Use on() and off(), that's what they are there for :

$('#do-login').on('click', login);

function login(e) {
    e.preventDefault();
    var that = $(this);
    that.off('click'); // remove handler
    $.ajax({
        type: "POST",
        url: "/php/auth/login.php",
        data: $("#login-form").serialize()
    }).done(function(msg) {
        // do stuff
    }).always(function() {
        that.on('click', login); // add handler back after ajax
    });
}); 

Upvotes: 44

000
000

Reputation: 27247

The problem is here:

    complete: function() {
        $(this).data('requestRunning', false);
    }

this no longer points to the button.

$('#do-login').click(function(e) {
    var me = $(this);
    e.preventDefault();

    if ( me.data('requestRunning') ) {
        return;
    }

    me.data('requestRunning', true);

    $.ajax({
        type: "POST",
        url: "/php/auth/login.php",
        data: $("#login-form").serialize(),
        success: function(msg) {
            //stuffs
        },
        complete: function() {
            me.data('requestRunning', false);
        }
    });      
}); 

Upvotes: 63

Vlad
Vlad

Reputation: 978

You can disable the button.

$(this).prop('disabled', true);

Upvotes: 5

Related Questions