2016-04-25 392 views
0

我只是最近才瞭解到jquery/javascript,而且我正面臨以下問題。for循環/遞歸中的執行順序

我想控制一個嵌套循環中的函數調用序列和/或在jquery/javascript中的遞歸。在我看來,現在所有函數幾乎同時被調用,並且不像我習慣於其他編程語言(如R)那樣遵循代碼中的順序。在R腳本中,只要代碼不會處理下一行當前的代碼行是未完成的。但似乎jQuery代碼同時觸發我的所有getJSON請求,並在1個結果可用時立即處理結果。它不關注getJSON調用的順序。這是真的,還是我錯過了什麼?幾次刷新頁面給我的結果集以不同的順序,而相同的順序會預期,一次又一次...

爲了解釋上述我創建了以下可行代碼,它使用api gridpointweather.com的插圖目的。

<!DOCTYPE html> 
<meta charset="utf-8"> 

<!--Body--> 
<body> 
    <div id="results"></div> 
</body> 

<!--Load jquery + uri.js--> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/URI.js/1.17.0/URI.min.js"></script> 

<script> 
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    // GLOBAL VARIABLES. 
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    var g_asLoc =       ["24", "42", "19"]; 
    var g_asWeather =      []; 

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

    function getWeatherInfo(location, offset){  
     console.log("Location: " + location); 
     console.log("Offset: " + offset); 
     var sUrl = 'http://api.gridpointweather.com/weather/getjson?location=' + location + '%2C-72&model=gfs.api0.n7m4csjf3x2s92ic&hours=24&inunits=1&interptype=2&offset=' + offset; 
     var requestUrl = sUrl; 
     $.getJSON(requestUrl, function(data) { 
      try { 
       console.log("Data for location " + location, data); 
      }catch(err) { 
       console.log(err); 
      } 

      // Store something. 
      $.each(data.data, function(index, weatherInfo){ 
       g_asWeather.push("Object " + index + ", Location: " + location + ", rawdate: " + weatherInfo.rawdate + ", Temp: " + weatherInfo.temp + "<br>"); 
      }); 

      // Offset with 25 if condition not met. 
      if(offset == -25){ 
       // Display in #results. 
       g_asWeather.push("<br><br>"); 
       $("#results").html(g_asWeather.join('\n')); 
       console.log("Finished for location " + location); 
       return; 
      }else{ 
       console.log("Running again using offset " + (offset-25) + " for location " + location); 
       getWeatherInfo(location, offset - 25); 
      } 
     }).error(function(){ 
       console.log("JSON error!"); 
       return; 
     }); 
    } 

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    // MAIN 
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    var iCounter = 0; 
    while(iCounter < 2){ 
     for(iLoc=0; iLoc<g_asLoc.length; iLoc++){ 
      getWeatherInfo(g_asLoc[iLoc], 0); 
     } 
     iCounter = iCounter + 1; 
    } 
</script> 

最好我想代碼調用的函數getWeatherInfo 1個位置,然後下一個位置繼續之前完成此地區的遞歸...遞歸的順序也很重要,因爲結果from offset = 0應該在g_asWeather之前,offset = 25的結果之前。在完成所有位置之後,代碼應等待,比如1000 ms,然後再將iCounter加1並重復for循環,而iCounter < 2.總結結果集應包含:iCounter = 0,位置24,偏移量= 0,偏移量= 25,位置42,偏移量= 0,偏移量= -25,位置19,偏移量= 0,偏移量= -25,等待1000ms,iCounter = 1,位置24,偏移量= 0,偏移量= -25等等等等。

非常感謝。

+1

while和for循環是同步的(按順序發生)但'getWeatherInfo'函數內的幾個語句是異步的(發生亂序)。這裏是一個[非常基本的入門](http://rowanmanning.com/posts/javascript-for-beginners-async/)同步vs異步javascript。更具體地說,'$ .getJSON'和'$ .each'函數都是異步的。基本上,只要解析器到達'$ .getJSON'函數,getWeatherInfo函數就會返回,for循環的下一次迭代將繼續。 –

+0

這就是我們承諾的原因。使異步程序流的工作變得容易。 – ste2425

+0

@MichaelL。這有助於理解爲什麼會出現這種情況。但是我必須確保for循環中的所有內容都是同步發生的。只要特定位置的位置信息(包括其偏移量)聚集在一起,位置的順序就不會讓我感到困擾。任何想法我可以做到這一點? –

回答

0

這是正確的,AJAX請求是異步的,所以你不知道在哪個命令結束每一個。你可以做的是創建一個數組來保存信息,並使用的索引for循環有數據排序,例如,而不是這樣做:

g_asWeather.push("Object " + index + ", Location: " + location + ", rawdate: " + weatherInfo.rawdate + ", Temp: " + weatherInfo.temp + "<br>"); 

你可以做這樣的事情(經過ILOC作爲參數):

g_asWeather[iLoc] = "Object " + index + ", Location: " + location + ", rawdate: " + weatherInfo.rawdate + ", Temp: " + weatherInfo.temp + "<br>"); 

所以你的陣列將由位置進行排序,如果你想訂購的一些其他方式排列,只是改變它將會被存儲在字符串變量。

+0

我需要強制執行的順序。我認爲你的解決方案可能有效,但是我必須管理哪個iCounter函數被調用。這可能會起作用,儘管異步請求讓我有點擔心。沒有更好的方法來做到這一點? –

+0

你可以這樣做,我用forEach代替傳統的代碼來提高可讀性。還加入了setTimeout來等待執行http://jsbin.com/memiwigezo/edit?html,js,output 我沒有找到更優雅的做法,提醒你強迫要有一個異步任務 –

+0

我接受了這個答案,因爲你的例子幫助我以相當直接的方式得到我想要的東西。雖然內置等待期不起作用。不管怎樣,謝謝你! –

0

要重申並擴展我的評論: while和for循環是同步的(按順序發生)但getWeatherInfo函數中的幾個語句是異步的(發生不按順序)。這裏是一個very basic primer on sync vs async javascript。更具體地說,$.getJSON$.each函數都是異步的。基本上,一旦解析器到達$.getJSON函數,getWeatherInfo函數就會返回並繼續進行for循環的下一次迭代。同樣,$.each函數的所有迭代都會一次性啓動(不是技術上真實,而是概念上),並且可以按任意順序完成。

位置的順序並沒有真正困擾我,只要一個特定位置的 位置信息(包括其偏移) 聚集。任何想法我可以做到這一點?

我建議改變你的數據結構,使g_asWeather對象(var g_asWeather = {};而不是var g_asWeather = [];)與作爲屬性的位置。你的$。每次循環會是這個樣子:

// Store something. 
$.each(data.data, function(index, weatherInfo){ 
    g_asWeather[location] = "Object " + index + ", Location: " + location + ", rawdate: " + weatherInfo.rawdate + ", Temp: " + weatherInfo.temp + "<br>"; 
}); 

要輸出的結果,是這樣的:

var results = ''; 
for (var location in g_asWeather) { 
    // This check is used because of some non-obvious ways that JavaScript can treat 
    // objects. http://phrogz.net/death-to-hasownproperty explains both why to 
    // use it and why not to. 
    if (!g_asWeather.hasOwnProperty(location)) continue; 

    results += g_asWeather[location] + '\n'; 
} 

$('#results').html(results); 

我也建議您更新循環外的DOM,但這是另一個問題。值得注意的是,儘管我使用「類似數組」的語法(方括號)來訪問對象,但這並不意味着該對象是一個數組,或者可以像對待一樣。

JavaScript允許使用幾種不同的語法來訪問對象屬性。當按名稱直接訪問屬性時,可以使用「點符號」,或者在將屬性名稱作爲字符串傳遞時使用方括號。考慮以下示例:

var foobar = { 
    a: 'foo', 
    b: 'bar' 
}; 

foobar.a; // 'foo' 
foobar['a']; // also 'foo' 

foobar.forEach(someCallback); // fails because it's not an array 
+0

我感謝你的解釋。 –