У меня есть скрипт, созданный специально для нестабильного подключения к Интернету, который позволяет отправлять форму один или несколько раз путем преобразования данных формы в 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>