2013-10-29 97 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... 
};