web-dev-qa-db-de.com

Ajax, mehrfache Anfrage auf Klick verhindern

Ich versuche, mehrere Anfragen zu verhindern, wenn der Benutzer auf die Schaltfläche Anmelden oder Registrieren klickt. Dies ist mein Code, aber es funktioniert nicht. Nur das erste Mal funktioniert gut, dann geben Sie false zurück.

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

Irgendwelche Ideen? Vielen Dank!

31
mauriblint

Das Problem ist hier:

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

this zeigt nicht mehr auf die Schaltfläche.

$('#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

Verwenden Sie on() und off(), dafür sind sie da:

$('#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

Sie können die Schaltfläche deaktivieren.

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

In Ihren Ajax-Callbacks ändert sich der Kontext (this) von der äußeren Funktion. Sie können ihn mit der Kontexteigenschaft in $ .ajax gleich einstellen

$.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

Sie können dies auch über die Schaltfläche oder den Link von $(this).addClass("disabled"); tun. Nachdem Sie den Klick ausgeführt haben, können Sie $(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. Wenn Sie Bootstrap-CSS verwenden, benötigen Sie den CSS-Teil nicht. 

0
Oskar

Ich fand den Ansatz nützlich. Ich habe es als allgemeine Funktion für jQuery mit ES6 implementiert.

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

Da $.ajax() ein Versprechen zurückgibt, geben Sie das Versprechen einfach ein und die Funktion erledigt den Rest.

Grob gesagt, hier ist die Verwendung.

import preventDoubleClick from './preventdoubleclick';

...

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

Diese Funktion kann Ihnen bei der Steuerung mehrerer Ajax-Anforderungen helfen und verfügt über eine Timeout-Funktion, die den Flag-Status nach ex auf 0 zurücksetzen kann. 10sec (Falls der Server mehr als 10 Sekunden benötigt hat, um zu antworten)

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

Um es zu benutzen:

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();
        }
    }); 
}
0

Ich habe auch ein ähnliches Problem konfrontiert.

Das Hinzufügen von $('#do-login').attr("disabled", true); gibt mir die Lösung.

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

Hier do-login ist die Schaltflächen-ID.

0
Atequer Rahman