2013-03-23 149 views
0

我有以下情況。我想從一個服務器加載文件A,反過來(取決於A的內容)將嘗試加載文件A1,A2,A3,... An,每個文件A[1-n]將依次加載其他文件,這可以繼續下去。是的,結束了。AJAX GET請求遞歸加載文件

不幸的是,我意識到我需要使用同步的$.ajax requests,否則第一個$ .ajax調用(當完成加載文件A時)只是返回而不通過其餘的文件。我的功能看起來像:

loadFile = function (path, file, scope) 
{ 
    $.ajax ({ 
     url: url, 
     type: 'GET', 
     dataType: 'text', 
     success: function (responseData) 
     { 
      var lines = responseData.split("\n"); 
      for (var j = 0; j < lines.length; j++) 
      { 
       if (lines[j].charAt(0) === 'F') 
        loadFile (arguments); 
      } 
     } 
    }); 
} 

我的第一個問題是,爲什麼我不能添加「異步:假」上面的選項,而是我必須使用$.ajaxSetup({async: false});,否則它不工作。

我的第二個問題是這是用於遞歸執行此工作的正確模式。

我的第三個問題是如何知道整個過程何時完成。我無法弄清楚這一點。

+0

由於JavaScript本身不能加載文件,爲什麼不處理服務器端的遞歸查找呢? – 2013-03-23 11:48:04

+0

加載文件確實有效(是的,這是一個瀏覽器拖延)但它是我正在開發的應用程序,所以我不確定你在服務器上加載的意思。 – gaitat 2013-03-23 11:54:24

+1

在JavaScript中同步請求的原因是一個可怕的想法是,JS是事件驅動和單線程 - 如果您阻止等待請求返回,則用戶無法滾動頁面上的任何內容或與其進行交互。我建議你看看JavaScript加載模式和異步模式(承諾和回調)。從外觀上看,您可以使用AMD系統 - 可以異步並行加載所有文件,並在加載完成後觸發所需的功能。 – 2013-03-23 12:18:15

回答

1

async: false是萬惡之源。它會阻止你的整個標籤頁,並且在某些情況下(比如較老的IE)會阻塞整個瀏覽器。不要使用它。

現在解決您的問題。你可以做這樣的事情:

// note new argument "callback" 
var loadFiles = function(path, file, scope, callback) { 
    var req = $.ajax({ 
     // some settings 
     success: function(res) { 
      // some processing 
      for (var j = 0; j < lines.length; j++) { 
       loadFiles.requests.push(
        // the same callback 
        loadFiles(path2, file2, scope2, callback) 
       ); 
      } 

      // set this request to complete 
      req.completed = true; 

      // check if all requests are done 
      for (var i = 0; i < loadFiles.requests.length; i++) { 
       if (!loadFiles.requests[i].completed) { 
        return; 
       } 
      } 
      // TODO: you could remove completed requests from that array 
      // to increase performance 

      // if all are done then reset the array and run the callback 
      delete loadFiles.requests; 
      if (callback) { 
       callback(); 
      } 
     } 
    }); 
    if (!loadFiles.requests || !loadFiles.requests.length) { 
     loadFiles.requests = [req]; 
    } 
    return req; 
}; 

loadFiles(path, file, scope, function() { 
    // this happens after all is done 
}); 

注意,在連續調用這個函數兩次將打破它(因爲loadFiles.requests是全局函數的一個屬性)。爲了支持這一點,你必須將所有東西都包含在外部函數中並使用該函數。

+0

對不起,我的無知,但回調()做什麼? – gaitat 2013-03-23 13:22:37

+0

@gaitat這是在所有事情完成後應該被解僱的功能。你在最後定義它(在我的代碼末尾傳遞給'loadFiles')。這就像AJAX的「成功」回調,除非**所有**作業完成後纔會觸發。 – freakish 2013-03-23 13:23:49

+0

我得到一個錯誤「無法讀取屬性'完成'的未定義」在「如果(!loadFiles.requests [i] .completed)」,並且總是當我是1時。 – gaitat 2013-03-23 17:33:12