![](/img/trans.png)
[英]refactor javascript for loop to use recursion to find the sum of a sequence of whole numbers
[英]Sequence of execution in for loop / recursion
我是最近才了解jquery / javascript的,并且面临以下问题。
我试图控制嵌套循环和/或jquery / javascript中的递归的函数调用顺序。 在我看来,现在几乎所有函数都被同时调用,并且不遵循我在其他编程语言(例如R)中惯用的顺序。在R脚本中,只要当前代码行未完成。 但是似乎jquery代码正在同时触发我的所有getJSON请求,并在1个结果可用时立即处理结果。 它不注意getJSON调用的顺序。 这是真的,还是我想念什么? 在下面几次刷新页面会给我不同顺序的结果集,而一次又一次地期望相同的顺序...
为了解释以上内容,我创建了以下可行的代码,该代码使用gridpointweather.com的api进行说明。
<!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>
最好是我希望代码为1个位置调用函数getWeatherInfo,然后在继续下一个位置之前完成该位置的递归...递归的顺序也很重要,因为offset = 0的结果应该在g_asWeather,在offset = 25的结果之前。 完成所有位置后,代码应等待1000 ms,然后将iCounter增大1,然后在iCounter <2时重复for循环。要总结结果集,应包含:iCounter = 0,位置24,offset = 0,offset =- 25,位置42,偏移量= 0,偏移量= -25,位置19,偏移量= 0,偏移量= -25,等待1000ms,iCounter = 1,位置24,偏移量= 0,偏移量= -25等,而iCounter <2 。
非常感激。
没错,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>");
因此,您的数组将根据位置进行排序,如果您想以其他方式对数组进行排序,只需更改要存储字符串的变量即可。
要再次重申和扩展我的评论:while和for循环是同步的(按顺序发生)然而, getWeatherInfo
函数中的几个语句是异步的(按顺序发生getWeatherInfo
)。 这是关于同步与异步JavaScript的非常基本的入门 。 更具体地说, $.getJSON
和$.each
函数都是异步的。 基本上,只要解析器到达$.getJSON
函数, getWeatherInfo
函数就会返回,并且for循环的下一次迭代将继续。 同样, $.each
函数的所有迭代都“一次性全部触发”(从技术上讲不是正确的,但从概念上讲),并且可以按任何顺序完成。
只要将特定位置的位置信息(包括其偏移量)聚集在一起,这些位置的顺序就不会真正困扰我。 知道我该如何实现吗?
我建议您更改数据结构,并使g_asWeather成为对象( var g_asWeather = {};
而不是var g_asWeather = [];
),并将位置作为属性。 您的$ .each循环如下所示:
// 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.