2013-10-29 98 views
0

我创建了一个简单的Chrome扩展,它遍历用户浏览历史记录并计算匹配特定编程语言数组的结果数量。问题是我想迭代数组的长度,并为数组列表中的每个字符串调用一个异步chrome方法。该扩展可以在这里找到: What type of programmer are you? 有问题的代码是:for循环中的异步方法

function myfunction() { 

    var listOfLanguages = ["Java", "C", "C++", "PHP", "C#", "Visual Basic", "Python", "Objective-C", "Perl", "Javascript", "Ruby"]; 
    var mostPopular = "not a programmer"; 
    var totalResults = 0; 


    for (var i = 0, len = listOfLanguages.length; i < len; i++) { 
     (function (i) { 
      setTimeout(function() { 

       chrome.history.search({ 
        text: listOfLanguages[i], 
        maxResults: 500 
       }, function (callback) { 

        var countOfResults = callback.length; 
        var langOfResults = listOfLanguages[i]; 


        if (countOfResults > totalResults) { 
         totalResults = countOfResults; 
         mostPopular = langOfResults; 
        } 

        if (i == 10) { 
         var lang = mostPopular; 
         console.log(mostPopular); 

         switch (lang) { 
         case "Java": 
          document.write('<img src="assets/images/java.png"/>'); 
          break;      
         case "C#": 
          document.write('<img src="assets/images/C#.jpg"/>'); 
          break; 
         case "C": 
          document.write('<img src="assets/images/C.png"/>'); 
          break; 
         case "C++": 
          document.write('<img src="assets/images/c++.png"/>'); 
          break; 
         case "Objective-C": 
          document.write('<img src="assets/images/objectivec.png"/>'); 
          break; 
         case "Perl": 
          document.write('<img src="assets/images/perl.gif"/>'); 
          break; 
         case "PHP": 
          document.write('<img src="assets/images/php.png"/>'); 
          break; 
         case "Python": 
          document.write('<img src="assets/images/python.jpg"/>'); 
          break; 
         case "Ruby": 
          document.write('<img src="assets/images/ruby.png"/>'); 
          break; 
         case "Visual Basic": 
          document.write('<img src="assets/images/vb.png"/>'); 

         default: 
          document.write('<img src="assets/images/noprog.png"/>'); 

         } 




        } 

       }); 

      }, i * 1000); 
     })(i); 
    } 



} 




window.onload = myfunction; 

我最终通过设置每次迭代里面超时功能周围找到一个工作,但它不是一个完美的解决方案。我已经在网上阅读了很多文章来处理这个问题,它们涉及到我不了解的更多层次的迭代。希望有人能够解释处理这个问题的正确方法,很多人都遇到过这个问题。

回答

1

做到这一点,最好的方法是计数,你必须出来和减量,因为他们回来异步调用的次数。

var outstandingCalls = 0; 
var resultSet = []; 
for (var i = 0; i < 100; i++) { 
    outstandingCalls++; 
    someAsyncCall(function(result) { 
     outstandingCalls--; 
     resultSet.push(result); 
     if (outstandingCalls == 0) done(); 
    }); 
} 
function done() { 
    //done... 
} 

(代码是未经证实的,但希望你的想法)

你也想确保你的for循环已经完成调用前完成();

1

如果我正确理解你,这样的事情可能会奏效。

取传递给setTimeout的匿名函数,并将其命名为函数。现在通过让它接受一组语言作为参数来使它成为一个递归函数。在函数结束时,删除第一种语言,然后递归剩余的数组。当数组为空时,停止递归。然后,以原始语言列表作为参数调用此函数。这样,下一个搜索迭代只会在当前结束时发生。

这是一段伪代码。

var search = function(languages) { 
    var currentLanguage = languages[0]; 

    //... 

    if (languages.length > 1) { 
     search(languages.slice(1)); 
    } 
}; 

search(listOfLanguages); 

编辑:另外考虑使用地图,而不是switch语句。地图语言来这样正确的图像:

var imageMap = { 
    "Objective-C": "objectivec.png", 
    "Visual Basic": "vb.png" 
    // etc... 
};