簡體   English   中英

Ajax請求等待直到第一個AJAX調用未完成

[英]Ajax Request Wait Until First AJAX Call not complete

我有以下代碼用於自動保存,但我同時有很多Ajax請求被觸發,我想等待Ajax請求直到第一個Ajax請求未完成

window.submitting = false;
$('form#AddForm').submit(function() {
    window.submitting = true;
});

var timeoutId;
$('form input, form textarea, form select').bind('input propertychange change', function() {
    console.log('Change');

    if (window.submitting)
        return false;

    clearTimeout(timeoutId);
    timeoutId = setTimeout(function() {
        // Runs 5 second (5000 ms)   
        autoSave();
    }, 5000);
});

function autoSave() {
    $.ajax({
        type: "POST",
        data: $('form#AddForm').serialize() + '&autosave=true',
        beforeSend: function(xhr) {
            // Let them know we are saving
            console.log('Saving........');
        },
        success: function(data) {
            var jqObj = jQuery(data); // Ajax call here.
            var ProductId = jqObj.find("#ProductId").val();
            var url = $(location).attr('href');
            var split = url.split("add");
            if (ProductId) {
                history.pushState({}, null, split[0] + "add/" + ProductId);
                $('#ProductId').val(ProductId);
                $('form#AddForm').attr('action', '/dataproducts/add/' + ProductId);
            }
        },
    });
}

看起來我已經抓住了你的問題。 如果用戶在表單元素上觸發了很少的更改事件,則會創建新的ajax請求,但在上一個處理過程之前不應該創建。

我猜您可以使用下一種方法:在發送ajax之前從表單元素取消綁定偵聽器 ,並在完成ajax時綁定它們

有關綁定/解除綁定的SO有一個很好的答案: 在jQuery中刪除事件處理程序的最佳方法是什么?

所以基本上你必須進行litle重構並添加幾行代碼:

window.submitting = false;
$('form#ProductAddForm').submit(function() {
    window.submitting = true;
});

var timeoutId;
var saveHandler = function() {
    console.log('Change');

    if (window.submitting)
        return false;

    clearTimeout(timeoutId);
    timeoutId = setTimeout(function() {
        // Runs 5 second (5000 ms)
        autoSave();
    }, 5000);
};

$('form input, form textarea, form select').bind('input propertychange change', saveHandler);

function autoSave() {
    // unbind events
    $('form input, form textarea, form select').unbind('input propertychange change')
    $.ajax({
        type: "POST",
        data: $('form#ProductAddForm').serialize() + '&autosave=true',
        beforeSend: function(xhr) {
            // Let them know we are saving
            console.log('Saving........');
        },
        success: function(data) {
            var jqObj = jQuery(data); // Ajax call here.
            var ProductId = jqObj.find("#ProductId").val();
            var url = $(location).attr('href');
            var split = url.split("add");
            if (ProductId) {
                history.pushState({}, null, split[0] + "add/" + ProductId);
                $('#ProductId').val(ProductId);
                $('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
            }
            // bind events back
            $('form input, form textarea, form select').bind('input propertychange change', saveHandler);
        },
        error: function{
            // bind events back even if reqeust fail
            $('form input, form textarea, form select').bind('input propertychange change', saveHandler);
        }
    });
}

注意不推薦使用jqXHR.successjqXHR.error ,有關詳細信息,請參閱$ .ajax 另外我添加了error方法,因為如果ajax失敗,你不能錯過綁定監聽器...

我可能誤解了這個問題,但我讀到了這樣的問題:

我不希望同時運行多個ajax請求。 但是當請求完成后,我想運行下一個請求。

你可以使用ajaxManager,就像jAndy在這里建議的那樣使用jQuery.queue()排隊ajax請求

var ajaxManager = (function() {
     var requests = [];

     return {
        addReq:  function(opt) {
            requests.push(opt);
        },
        removeReq:  function(opt) {
            if( $.inArray(opt, requests) > -1 )
                requests.splice($.inArray(opt, requests), 1);
        },
        run: function() {
            var self = this,
                oriSuc;

            if( requests.length ) {
                oriSuc = requests[0].complete;

                requests[0].complete = function() {
                     if( typeof(oriSuc) === 'function' ) oriSuc();
                     requests.shift();
                     self.run.apply(self, []);
                };   

                $.ajax(requests[0]);
            } else {
              self.tid = setTimeout(function() {
                 self.run.apply(self, []);
              }, 1000);
            }
        },
        stop:  function() {
            requests = [];
            clearTimeout(this.tid);
        }
     };
}());

並在您的代碼中使用它:

ajaxManager.run(); 

function autoSave() {
    ajaxManager.addReq({
        type: "POST",
        data: $('form#ProductAddForm').serialize() + '&autosave=true',
        beforeSend: function(xhr) {
            // Let them know we are saving
            console.log('Saving........');
        },
        success: function(data) {
            var jqObj = jQuery(data); // Ajax call here.
            var ProductId = jqObj.find("#ProductId").val();
            var url = $(location).attr('href');
            var split = url.split("add");
            if (ProductId) {
                history.pushState({}, null, split[0] + "add/" + ProductId);
                $('#ProductId').val(ProductId);
                $('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
            }
        },
    });
}

這樣您就可以排隊不同的請求。 但是,通過代碼,您似乎總是發送整個表單。 那么,如果下一個請求會發布更准確的值,為什么第一個請求會完成呢? 顯然有理由說你可能想發布每一個變化。 但如果沒有,您可以取消之前的請求並發送另一個請求。

var xhr;

function autoSave() {
    if(xhr){
       //TODO: Check if there is a current call.
       // abort call.
       xhr.abort();
    }
    xhr = $.ajax({
        type: "POST",
        data: $('form#ProductAddForm').serialize() + '&autosave=true',
        beforeSend: function(xhr) {
            // Let them know we are saving
            console.log('Saving........');
        },
        success: function(data) {
            var jqObj = jQuery(data); // Ajax call here.
            var ProductId = jqObj.find("#ProductId").val();
            var url = $(location).attr('href');
            var split = url.split("add");
            if (ProductId) {
                history.pushState({}, null, split[0] + "add/" + ProductId);
                $('#ProductId').val(ProductId);
                $('form#ProductAddForm').attr('action', '/account/products/add/' + ProductId);
            }
        },
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM