2013-01-21 56 views
2

我有一個函數,它需要一個參數並進行同步加載。JavaScript如何停止等待延遲完成?

我改變它做異步jQuery.ajax調用來檢索數據並調用回調。舊代碼(無法修改)使用相同的功能並失敗。我需要能夠以兩種方式檢索數據,以便異步代碼可以繼續運行,並且如果異步已經加載,舊同步代碼可以檢索緩存的數據,同步加載它或等待已經運行的任何異步請求。

var ajaxQueries = {} 
loadEngineData(fileId, callback) { 
    var sync = callback == undefined; 
    if (ajaxQueries[fileId]) { 
     if (sync) { 
      //Need to stop here and wait for ajaxQueries[fileId] to finish 
      //Execution cannot continue! If we return before defered has ended here 3rd party scripts will fail. 
      return data; 
     } 
     else { 
      ajaxQueries[fileId].done(function(data){callback(data)}); 
     } 
    } 
    else { 
     ajaxQueries[fileId] = $.ajax({ 
      async:!sync, 
      type:'GET', 
      url:fileId2Name(fileId), 
      data:null, 
      dataType:'text', 
     }); 
     if (sync) { 
      var _data = undefined; 
      ajaxQueries[fileId].done(function(data){_data=data}); 
      return _data; 
     } 
     ajaxQueries[fileId].done(function(data){callback(data);}); 
    } 
} 

如果老腳本調用Ajax的查詢將同步運行的功能,所有後續調用將使用遞延.done.fail,一切都會好起來的。

var enginePhyData = loadEngineData('physics'); 
//Do stuff 

如果一個新的腳本調用函數首先,這加載一箇舊腳本試圖從同一個文件中加載數據時,我結束與其中ajaxQueries[fileId]遞延AJAX查詢異步運行的情況下,我必須等待它完成加載數據以避免打破現有的庫。

我簡化了loadEngineData以保持問題的重點。否則,它更復雜一點,並允許調用文件的列表並行

loadEngineData(['geometry', 'scripts'], function() { 
    var phy = loadEngineData('physics'); 
    var geo = loadEngineData('geometry'); 
    var scr = loadEngineData('scripts'); 

    //run the async function; 
}); 
loadEngineData('physics', function() { 
    //run the async function; 
}); 

//... 
//in the scripts file 

var phy = loadEngineData('physics'); 
//here phy might be undefined if this file went through eval() before `loadEngineData('physics',...)` was called; 

我可以現代化的代碼加載,但問題是,有些文件是跨項目共享,並在不同的環境中運行。我目前無法修改舊腳本而不分散依賴關係。

+2

您試圖使異步代碼同步,這將無法正常工作。你不能停止代碼執行,直到x條件,沒有可能的破壞性的副作用。 –

+0

您的選擇是:單獨保留舊方法並製作新方法,以便舊方法可以繼續同步工作,或者修改舊代碼的工作方式以使其異步工作。 –

+0

@KevinB:據我所知調用'$ .ajax({async:false,...});'停止代碼執行。或者我錯了? – Coyote

回答

4

在等待某個異步ajax調用完成時,您無法停止執行javascript。 JavaScript根本不會這樣工作。

相反,您必須重新編寫程序,以便希望等待異步ajax調用完成的代碼將通過回調函數執行,而不是在執行ajax調用後同步執行。

1

你很近,如果它是一個同步請求,你只需要返回responseText。

return data 

成爲

return ajaxQueries[fileId].responseText; 

因爲該請求是同步的,沒有必要等待,瀏覽器已經等待響應。

var ajaxQueries = {} 
loadEngineData(fileId, callback) { 
    var sync = callback == undefined; 
    if (ajaxQueries[fileId]) { 
     if (sync) { 
      return ajaxQueries[fileId].responseText; 
     } 
     else { 
      ... 
+0

我缺少的是等待異步請求完成的代碼,如果腳本調用期望返回響應的函數。 'ajaxQueries [fileId]'中的ajax查詢可能還沒有結束,因爲它可能是異步啓動的,在這種情況下,我返回'undefined',腳本失敗。 – Coyote

+0

如果同步爲false,它將永遠不會進入該部分,並將其發送到正確處理異步請求的其他位置,這意味着它的同步數據將在第一次和後續時間從該方法返回,並且如果它是異步,提供的回調將在請求時調用。現在,如果您發出同步請求並將其用作異步(反之亦然),則可能會遇到問題。 –