web-dev-qa-db-fra.com

Ajax, empêchez les demandes multiples au clic

J'essaie d'empêcher les demandes multiples lorsque l'utilisateur clique sur le bouton de connexion ou d'enregistrement. Ceci est mon code, mais cela ne fonctionne pas. Juste la première fois fonctionne bien, puis retourne 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);
        }
    });      
}); 

Des idées? Merci!

31
mauriblint

Le problème est ici:

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

this ne pointe plus le bouton.

$('#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);
        }
    });      
}); 
49
Joe Frambach

Utilisez on() et off(), c’est leur fonction:

$('#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
    });
}); 
41
adeneo

Vous pouvez désactiver le bouton.

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

Dans vos rappels ajax, le contexte (this) change par rapport à la fonction externe. Vous pouvez le définir de la même manière en utilisant la propriété context dans $ .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);
    }
});      
3
Musa

Ou vous pouvez le faire par $(this).addClass("disabled"); à votre bouton ou lien et après avoir cliqué, vous pouvez $(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. Si vous utilisez bootstrap css, vous n’avez pas besoin de la partie css. 

0
Oskar

J'ai trouvé l'approche utile. Je l'ai implémentée en tant que fonction polyvalente pour jQuery avec 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);
    });
}

Étant donné que $.ajax() renvoie une promesse, il vous suffit de la transmettre et la fonction s'occupe du reste.

En gros, voici l'usage.

import preventDoubleClick from './preventdoubleclick';

...

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