Подтвердить что ты не робот

Ajax, предотвращать множественный запрос при нажатии

Я пытаюсь предотвратить несколько запросов, когда пользователь нажимает кнопку входа или регистрации. Это мой код, но он не работает. Просто первый раз отлично работает, а затем возвращает 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);
        }
    });      
}); 

Любые идеи? Спасибо!

4b9b3361

Ответ 1

Проблема здесь:

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

this больше не указывает на кнопку.

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

Ответ 2

Используйте on() и off(), что они там для:

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

Ответ 3

Вы можете отключить кнопку.

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

Ответ 4

В ваших обратных вызовах ajax контекст (this) изменяется от внешней функции, вы можете установить его таким же, используя свойство context в $.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);
    }
});      

Ответ 5

Или вы можете сделать это нажатием $(this).addClass("disabled"); на кнопку или ссылку, и после нажатия нажмите $(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. Если вы используете bootstrap css, вам не нужна часть css.

Ответ 6

Я нашел подход полезным. Я реализовал его как функцию общего назначения для jQuery с 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);
    });
}

Поскольку $.ajax() возвращает обещание, вы просто передаете обещание, и функция позаботится об остальном.

Грубо говоря, здесь использование.

import preventDoubleClick from './preventdoubleclick';

...

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

Ответ 7

Эта функция может помочь вам управлять несколькими Ajax-запросами и имеет функцию тайм-аута, которая может возвращать статус флага в 0 после ex. 10 секунд (в случае ответа сервера более 10 секунд)

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

Чтобы использовать это:

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

Ответ 8

Я также столкнулся с подобной проблемой.

Просто добавьте $('#do-login').attr("disabled", true); дает мне решение.

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

Здесь do-login это идентификатор кнопки.

Ответ 9

для предотвращения множественного запроса ajax на всем сайте. Например: Если вы используете ajax-запрос на другой странице ajax, используя ajax в php-цикле и т.д., Дайте вам несколько запросов ajax с одним результатом. У меня есть решение:

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

вместо

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

на главной странице index.php. Его будет предотвращать все запросы.:)