JQuery AJAX стрельбы дважды, когда снова в сети - PullRequest
1 голос
/ 30 апреля 2019

У меня есть скрипт, созданный специально для нестабильного подключения к Интернету, который позволяет отправлять форму один или несколько раз путем преобразования данных формы в JSON (используя JSON.stringify) и перемещения его содержимого в скрытое поле <textarea> при отправке.А пока давайте назовем это скрытое поле dataCache.

Когда форма отправляется и обрабатывается в dataCache, немедленно вызывается функция с именем processDataCache(), которая пыталась обработать / сохранить данныес вызовом jQuery $.ajax().В случае успеха dataCache очищается.Если нет, например, у нас нет подключения к Интернету, вызывается setInterval, чтобы повторить вызов на processDataCache() через несколько секунд.

Тем временем, если форма отправляется снова, она добавляет содержимое вdataCache, разделяющий любое существующее содержимое с помощью уникального разделителя.

В конце концов, как только подключение к Интернету снова становится доступным, processDataCache() обрабатывает вызов и dataCache очищается.

Этоотлично работает, когда онлайн с одним или несколькими элементами в dataCache.НО моя текущая проблема заключается в том, что когда форма переходит в автономный режим и один или несколько элементов добавляются в dataCache, $.ajax() почти всегда срабатывает дважды при возвращении в онлайн.Я говорю почти , потому что это происходит примерно в 75% случаев, но не каждый раз.Интересно, что если я добавлю console.log к параметру success $.ajax(), он будет отображаться только один раз, как если бы он был вызван только один раз, но данные обрабатываются дважды независимо от этого.

Ниже приводитсякод, имеющий проблему.Он также включает в себя пакетный процесс, который делает его немного более сложным, чем я обрисовал в общих чертах, который решает ограничения POST, но основной принцип такой же, как я упоминал выше:

<textarea id="dataLogCacheFile" style="display:none;"></textarea>

<script>
var maxEventsForBatchProcess = 5; // set to highest amount POST will allow cross-browser, considering each event will likely be around 400 chars (e.g. 5 for ~2000 char limit)
var nRetryAddEventTime = 5000; // every 5 seconds - if batch fails (e.g. no connection), how long to wait until trying again
var nAddNextEventsTime = 1000; // every 1 seconds - once a batch completes, time to wait until next batch begins
var cacheDelim = "##--##"; // delimiter for events in cache, must be unique and be the same as what the nEventProcessURL expects
var processingCache = false;
var nEventProcessURL = "process_cache.php";
var eventProcessRepeater;

function saveEventToCache(xProcess){
    var nNewDataARRAY = $("#MyForm").serializeObject(); // pull in form data
    var nNewData = JSON.stringify(nNewDataARRAY);
    var nDataLogCache = $("#dataLogCacheFile").val(); // pull in existing cache
    var nDataLogCacheARRAY = [];
    if(nDataLogCache){ nDataLogCacheARRAY = nDataLogCache.split(cacheDelim); }
    if(nNewData){ nDataLogCacheARRAY.push(nNewData); } // add new event to cache
    // update cache field
    nDataLogCache = nDataLogCacheARRAY.join(cacheDelim);
    $("#dataLogCacheFile").val(nDataLogCache);
    if(xProcess){ processEventCache(); } // try to process it
    return false;
}

var nRetryCount = 0;
function processEventCache(){
    var nDataLogCache = $("#dataLogCacheFile").val(); // pull in existing cache
    if( nDataLogCache ){
        processingCache = true;
        nDataLogCacheARRAY = nDataLogCache.split(cacheDelim);
        var nEventsToProcessARRAY = [], nEventsToCacheARRAY = [];
        for(var i = 0; i < nDataLogCacheARRAY.length; i++) {
            if(i < maxEventsForBatchProcess){ nEventsToProcessARRAY.push( nDataLogCacheARRAY[i] ); } else { nEventsToCacheARRAY.push( nDataLogCacheARRAY[i] ); }
        }
        if(nEventsToProcessARRAY.length){
            var nEventsToProcess = nEventsToProcessARRAY.join(cacheDelim);
            var cacheProcessAjaxRequest = $.ajax({
                type: "POST", url: nEventProcessURL, data: "nEventCache="+nEventsToProcess,  
                error: function(msg,msg2,errorMsg){
                    cacheProcessAjaxRequest.abort();
                    nRetryCount++;
                    if(!eventProcessRepeater){
                        eventProcessRepeater = setInterval(processEventCache,nRetryAddEventTime);
                    }
                },
                success: function(nCurrDateTime) {
                    // update cache field
                    nDataLogCache = nEventsToCacheARRAY.join(cacheDelim);
                    $("#dataLogCacheFile").val(nDataLogCache);
                    // if there are more events to process, keep going, otherwise close up shop
                    if(nDataLogCache){
                        setTimeout(function(){ processEventCache(); },nAddNextEventsTime); // wait a bit before processing next batch of events
                    } else {
                        processingCache = false;
                    }
                }
            });
        } else {
            processingCache = false;
        }
        // Turn off any additional processing threads if they're no longer needed
        if(!processingCache && eventProcessRepeater){ clearInterval(eventProcessRepeater); eventProcessRepeater = ""; }
    } else {
        processingCache = false;
    }
}
</script>

1 Ответ

0 голосов
/ 02 мая 2019

Что ж, я нашел способ решить проблему, не понимая, что происходит, но, ну да, иногда вам просто нужно двигаться вперед.

После выбранного ответа на этой теме Я обновил свой код выше до этого (просто показывая соответствующие строки):

var cacheProcessAjaxRequest = { abort:function(){} };
function processEventCache(){
    ...
    cacheProcessAjaxRequest.abort(); // abort any other pending processing
    cacheProcessAjaxRequest = $.ajax({
        ...
    });
    ...
}

Я также удалил предыдущую строку cacheProcessAjaxRequest.abort(); в параметре error:.

С этим исправлением двойная обработка все еще происходила, но гораздо реже. Чтобы сделать еще один шаг вперед, я добавил переменную для отслеживания количества процессов, связанных с кэшем, и разрешил вызов $.ajax(), только если это число было равно нулю. Похоже, что эти двое вместе решают проблему полностью ... после примерно 50 тестов я больше не сталкивался с двойной обработкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...