2015-06-18 99 views
0

所以一切正常,問題是如果發現衝突它會調用showInstConflicts(allconflicts, joined);兩次......調試顯示它評估真實兩次,但我無法弄清楚它是如何可能的。當沒有衝突時,它不會調用兩次函數generatePDF()爲什麼多個Ajax查詢循環運行成功兩次?

我正在使用的表格根據教師現有的時間表檢查提議的時間表(我們正在使用的表格),以查看是否存在衝突。有時,教師可以有多個會議時間像一個類:

  1. MWF,一七三〇年至1930年,一月12日至5月5日,建築物ROOM
  2. TR,1200-0100,一月12日至5月5日,建築物ROOM2

在這種情況下,ajax檢查需要運行兩次以確保BOTH會議時間沒有衝突。

的循環計數與nodata次發現的數量,檢查,看看它是否檢查足夠的時間(joined.length這是次次檢查數組),如果有至少一次當數據(又名衝突)收到了。如果發現至少有一個success調用,則在所有檢查完成後(i==times),調用顯示功能showInstConflicts(),顯示衝突。

如果nodata數高達

我使用的是個人的jQuery插件.JSONTable()它只是使一個$.ajax呼叫,並格式化爲基於定義的設置的表。當ajax返回data.length < 1時調用nodata:

因此,這裏的循環:

var times = joined.length; 
var nodata = 0; 
var allconflicts = $('<div></div>'); 

for (i = 0; i < times; i++) { 
    var conflicts = $('<div></div>').appendTo(allconflicts); 
    //use $.JSONTable plugin (see plugins.js) to check instructor conflicts 
    conflicts.JSONTable({ 
     url: '/ajax/ajaxCSFInstCheck.php', 
     options: joined[i], 
     noWraps: ['allrows'], 
     columns: ['Name', 'Primary', 'Responsible', 'CRN', 'Class', 'Dates', 'Days', 'Times', 'Location', 'XST', 'Web', 'All Meetings'], 
     responsive: true, 
     success: function() { 
      //if conflicts found, show on the final ajax return 
      //*** this is evaluating true twice per run *** 
      if (i == times && nodata < times) { 
       showInstConflicts(allconflicts, joined); 
      } 
     }, 
     nodata: function() { 
      //if no conflicts found, make the PDF 
      nodata++; 
      if (i == times && nodata == times) { 
       generatePDF(); 
      } 
     } 
    }); 

} 

$.fn.JSONTable的代碼是在我的網站http://curric.uaa.alaska.edu/js/plugins.js,該文件的後半部分。

+0

插件是否讓您可以選擇一次獲取多個表格?一次發射多個XHR請求效率不高。似乎不幸的是必須同時向* same * URL發送多個請求。 –

+0

問題是我需要根據教師的現有時間表檢查一次會議時間數組,以查看是否有任何衝突。我必須分別檢查每一個(否則MySQL查詢變得非常昂貴)。因此,雖然插件可以配置爲一次發送多個會議時間,但查詢無法處理它。大多數情況下,這隻會運行一次或兩次,只能運行超過兩次的真正複雜的課程計劃 –

+0

我明白了。這就說得通了。 –

回答

2

因此,它看起來像JSONTable是一個Ajax調用。這意味着它是異步的。因此,您的for循環將立即啓動所有異步調用,並且當第一個完成時,索引i將處於循環結束時的值。另外,您的Ajax調用可以以任意順序完成。

如果您想查看與該特定Ajax調用相對應的i的正確值,那麼您必須將i放入一個閉包中,以便爲每個Ajax調用保留唯一的值。

如果您希望Ajax調用按照嚴格的順序執行,那麼您將不得不重構如何運行它們(您不能使用直接for循環)。

這裏是你將如何保存的i值對每個單獨的Ajax調用:

var times = joined.length; 
var nodata = 0; 
var allconflicts = $('<div></div>'); 

for (var i = 0; i < times; i++) { 
    // create closure to capture the value of i 
    (function(i) { 
     var conflicts = $('<div></div>').appendTo(allconflicts); 
     //use $.JSONTable plugin (see plugins.js) to check instructor conflicts 
     conflicts.JSONTable({ 
      url: '/ajax/ajaxCSFInstCheck.php', 
      options: joined[i], 
      noWraps: ['allrows'], 
      columns: ['Name', 'Primary', 'Responsible', 'CRN', 'Class', 'Dates', 'Days', 'Times', 'Location', 'XST', 'Web', 'All Meetings'], 
      responsive: true, 
      success: function() { 
       //if conflicts found, show on the final ajax return 
       //*** this is evaluating true twice per run *** 
       if (i == times && nodata < times) { 
        showInstConflicts(allconflicts, joined); 
       } 
      }, 
      nodata: function() { 
       //if no conflicts found, make the PDF 
       nodata++; 
       if (i == times && nodata == times) { 
        generatePDF(); 
       } 
      } 
     }); 
    })(i); 
} 

我有以下你想究竟如何處理所有這些數據很難。一般來說,如果您要檢索N段異步數據,並且您希望對此數據執行的操作需要查看多個異步結果,那麼最簡單的方法是收集所有數據(通常是數組),然後當您擁有所有數據時,最後一次處理所有結果。然後,任何內部相關性都可以被查看一次。

當使用多個ajax調用時,通常最簡單的方法是使用promise並讓promise基礎設施收集所有結果,並在所有ajax調用完成時(可能使用Promise.all())將其傳遞到數組中的回調中。

+0

封閉解決了這個問題(也確認我有一些小的櫃檯問題)。你是對的,雖然編譯多個Ajax請求後的承諾是一個更優雅的解決方案。如果我能得到時間,我會轉向那個。謝謝一堆! –