2016-04-25 386 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

我感谢你的解释。 –