2013-03-07 56 views
4

我有以下JavaScript代碼遍歷頁面上的文本列表。它將文本字段中的文本作爲價格,通過AJAX GET將其發送到服務器,並從服務器獲取解析的雙重文件。如果任何退貨價格低於現有價格,則表單不應提交。jQuery Ajax Race Condition?

問題在於,由於Ajax調用的非阻塞即時響應性質,表單在所有AJAX請求完成之前提交。我需要設置一個wait()函數(或所有Ajax方法完成時的回調函數),但不知道如何使用jQuery來實現。

有什麼建議嗎?

// .submitForm is a simple button type="button", not type="submit" 
$(".submitForm").click(function(e){ 
    var submittable = validatePrices(); 
    if (submittable) { 
    $("#myForm").submit(); 
    } 
}); 

function validatePrices() { 
    var submittable = true; 

    $(".productPrice").each(function(){ 
     var $el = $(this); 

     $.ajax({ 
      type: "POST", 
      url: "/get_price.jsp", 
      async: false, 
      dataType: "html", 
      data: "price=" + $el.val(), 
      success: function(data) 
      {     
       var price = new Number(data.split("|")[1]); 
       var minPrice = new Number($el.data("min-price")); 
       if (price < minPrice) 
       { 
        $el.addClass("error"); 
        $(".dynamicMessage").show().addClass("error").append("<p>ERROR</p>"); 
        submittable = false; 
       } 
      } 
     }); 
     return submittable; 
    }); 
} 
+0

'e.preventDefault()' – Bergi 2013-03-07 17:18:52

+0

對每個單獨的字段使用同步HTTP請求回到您的服務器將使您的網站非常緩慢。 – Pointy 2013-03-07 17:19:51

+0

已更新帖子以闡明.submitForm不是type =「submit」,只是一個type =「button」,因此不需要e.preventDefault()。 – bluedevil2k 2013-03-07 17:25:05

回答

4

您已經在使用同步AJAX(對您的用戶體驗來說這是一個非常糟糕的主意),所以這不是問題。問題是,你需要取消的默認操作中的「提交」處理程序:

$(".submitForm").click(function(e){ 
    var submittable = validatePrices(); 
    e.preventDefault(); // this line 
    if (submittable) { 
    $("#myForm").submit(); 
    } 
}); 

使用同步HTTP請求返回到您的服務器爲每個單獨的字段將會使您的網站非常緩慢。無論如何,當您提交表單時,您將不得不再次檢查服務器上的參數,因此只需檢查然後返回錯誤就會好得多。

編輯 —現在情況更清楚了,我認爲要繼續完成AJAX驗證檢查的方法。爲什麼?那麼,即使你進行了這些測試,你仍然需要在實際提交表單時進行基本上相同的有效性測試。您不能依賴實際運行的JavaScript驗證代碼,就像在任何其他表單驗證場景中一樣。如果您在表單提交時進行驗證,它將節省大量HTTP請求,以便同時完成所有操作。

+1

對,我把它改爲異步:假以得到它的工作,但我在尋找合適的Ajax的異步方式。 e.preventDefault()不能解決它,因爲按鈕不是type =「submit」 – bluedevil2k 2013-03-07 17:52:46

+0

@ bluedevil2k好了,清除問題。正如我寫的,我認爲做到這一點的真正「正確方法」是簡單地在服務器上進行所有驗證。無論如何,你必須在表單處理器(在服務器端)執行它,因爲你無法確定javascript測試已經完成。 – Pointy 2013-03-07 18:11:09

+0

我現在傾向於混合解決方案。我做的文本框的模糊()價格的驗證,並設置一個全局變量submittable上穿過(與異步:真)上的。如果他們直接從文本框中按下「保存」按鈕,則Ajax調用將不會完成,並會轉到服務器端驗證。 – bluedevil2k 2013-03-07 18:35:13

1

您並未取消表單提交。你必須嚴格使用ajax回調函數(如果你想異步使用它們,那會很好)。

$(".submitForm").click(function(e){ 
    e.preventDefault(); 
    validatePrices().done(function() { /* ajax success function here */ 
     if (submittable) { 
      $("#myform").trigger('submit'); 
     } 
    } 
}); 

function validatePrices() { 
    var checks = []; 

    $(".productPrice").each(function(){ 
     var $el = $(this); 
     checks.push($.ajax({ 
      /* snip */ 
    }); 
    return $.when.apply(null, checks); 

} 
+0

我認爲你的答案很接近,但第一個函數不起作用,因爲沒有創建可提交的變量。如何將submittable變量從validatePrices()傳遞迴click()函數? – bluedevil2k 2013-03-07 17:32:20

+0

@ bluedevil2k我只是用這個作爲例子..你可以做的是存儲'submittable'(或一些模擬)並在每個單獨的ajax回調期間寫入它,然後在'$ .when'完成回調中檢查它 – 2013-03-07 18:05:06