Внешний интерфейс предотвращает повторную отправку пользователями - js

задняя часть внешний интерфейс JavaScript jQuery
Внешний интерфейс предотвращает повторную отправку пользователями - js

задний план

Когда интерфейс отправляет данные на сервер, обычно необходимо, чтобы пользователь не мог быстро щелкнуть, чтобы отправить второй запрос, прежде чем вернется первый запрос, то есть предотвратить повторные отправки.Самый простой способ — использовать параметры флага. или элементы класса для управления, но недостатком является то, что эту логику нужно добавлять в каждое место, которое контролирует повторные отправки, повторение слишком сильное, а логика управления не унифицирована.

В настоящее время внешний интерфейс использует протокол http, поэтому есть два способа отправки.

  • Асинхронная отправка с использованием jQuery.ajax()
  • синхронная подача формы

Схема асинхронной антидубликационной подачи выглядит следующим образом

С помощью метода ajaxPrefilter, предоставляемого jQuery, запрос будет отфильтрован до того, как запрос будет отправлен, будет сохранен только первый запрос, а последующие запросы будут заблокированы от прерывания. Конкретный код реализации выглядит следующим образом.

/**
 * _pendingRequests = {
 *  'http:xxx.xxxx.do':['domain=P2P','xxxx=aaa'],
 *  'http:xxx.yyyy.do':['domain=P3P','xxxx=bbb']
 * }
 * 该对象的 key 是请求的 url ,value 是由请求参数转化成的字符串数组
 */
var _pendingRequests = {};
$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
    var p_item = {  //保存请求请求的url
            key:options.url,
            index:0
        },
        dataArray = options.data ? options.data.split('&') : [];
        compareData = function(beforD,afterD) {
            //当url相同时,以此比较保存的参数对象,若参数对象相同,则返回false,若第一个就相同,则跳出循环
            // 反之说明当前参数对象列表中没有与将要提交的参数相同,则可看为不同的请求,返回true,允许发起请求
            var result  = false;
            for(var i=0;i<beforD.length;i++){
                if(beforD[i]){
                    result = false;
                    var beforData = beforD[i];
                    for(var j=0;j<beforData.length;j++){
                        if(afterD[j] !== beforData[j]){
                            result = true;
                            break;
                        }
                    }
                    if (!result){
                        break;
                    }
                }else {
                    result = true;
                    continue;
                }
            }
            return result;
        };

    //若请求队列中不存在或者同一个请求不同参数,且不为html后缀,则加入队列中
    if (( !_pendingRequests[p_item.key] || compareData(_pendingRequests[p_item.key],dataArray) ) && p_item.key.indexOf('.html') === -1) {
        //给 index 赋值是因为请求是异步返回的,index用于标记第一个请求
        if(_pendingRequests[p_item.key]){
            p_item.index = _pendingRequests[p_item.key].push(dataArray)-1;
        } else{
            _pendingRequests[p_item.key] = [dataArray];
            p_item.index = 0;
        }
    } else if (p_item.key.indexOf('.html') === -1) {
        jqXHR.abort();	// 放弃后触发的重复提交,仅保留第一次提交
        //pendingRequests[key].abort();	// 放弃先触发的提交
    }
    var complete = options.complete;
    //请求完成
    options.complete = function(jqXHR, textStatus) {
        // 通过 key 和 index 获取成功返回的请求,将其值为 null ,下一次该请求便是在请求队列中便是新的一个请求
        _pendingRequests[p_item.key][p_item.index] = null;
        if ($.isFunction(complete)) {
            complete.apply(this, arguments);
        }
    };
});

jquery.ajaxprefilter официальная документация

Схема подачи формы антидубликатной подачи выглядит следующим образом

Обработка формы немного сложнее, но общая идея та же, что и у асинхронной: во время ожидания возврата первого запроса предотвращается отправка последующих инициированных запросов. Во-первых, пользовательский метод расширяется на основе jquery следующим образом.

$.fn.preventDoubleSubmission = function() {
    $(this).on('submit', function(e) {
        var $form = $(this);
        // $form.data('submitted') 通过该变量判断请求的状态
        if ($form.data('submitted') === true) {
            //阻止请求
            e.preventDefault();
        } else {
            $form.data('submitted', true);
            if ($form.attr('target') === '_blank') {
                setTimeout(function() {
                    $form.data('submitted', false);
                }, 800);
            }
        }
    });
    return this;
};

Когда форма отправляется в первый раз, через jQuery.data() устанавливается флаг. При повторной отправке формы оценивается установленный флаг. Если форма находится в состоянии отправки, событие отправки формы будет заблокирован. Когда form.target = _blank и после отправки открывается новый интерфейс, состояние отправки формы исходного интерфейса будет восстановлено через 800 миллисекунд.

Чтобы упростить унифицированную обработку отправленных форм на сайте, к форме, которую необходимо повторно отправлять, можно добавить класс.preventDouble, После рендеринга страницы добавьте единообразно отслеживание событий

//扫描带有 preventDouble 标识的form表单
$(function() {
    var f = $('.contain form.preventDouble');
    for (var i=0;i<f.length;i++){
        $(f[i]).preventDoubleSubmission();
    }
});

Советы

Кнопку отправки нужно использоватьtype=’submit’, потому что он прослушивает событие отправки формы Не рекомендуется прослушивать событие отправки несколько раз, что приведет к сбою повторной отправки. Обычно перед отправкой формы выполняются некоторые операции проверки формы, поэтому, если проверка не удалась, вы можете пройтиevent.preventDefault()предотвратить отправку формы