2013-09-12 2 views
21

Я пытаюсь предотвратить множественные запросы, когда пользователь нажимает кнопку входа или регистрации. Это мой код, но он не работает. Только в первый раз отлично работает, а затем возвращается false.Ajax, предотвратить множественный запрос при нажатии

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

Любые идеи? Благодаря!

ответ

36

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

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

Это очень гениальная идея. Работает как шарм. –

+0

Спасибо. Ты спас свой день. – gihandilanka

4

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

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

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

Спасибо за объяснение опции 'context' –

30

Использование 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 
    }); 
}); 
+1

Спасибо! Решение Joe отлично работает. но этот другой способ получить тот же результат. Какое из лучших решений? – mauriblint

+0

@ Решение adeneo лучше. –

+0

@JoeFrambach - спасибо, но это действительно вопрос предпочтения, нет ничего плохого в установке флага в data(), но это похоже на то, что предназначалось для выполнения функций on() и off(), добавления и удаления обработчиков событий ? – adeneo

0

или вы можете сделать это $(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

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

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

вместо

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

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

0

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