0

我创建了一个简单的 chrome 扩展,它迭代用户浏览历史并计算与特定编程语言数组匹配的结果数量。问题是我想迭代数组的长度并为数组列表中的每个字符串调用一个异步 chrome 方法。扩展可以在这里找到: 你是什么类型的程序员? 有问题的代码是:

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;

我最终通过在每次迭代中设置超时函数找到了解决方法,但这不是一个优雅的解决方案。我已经在网上阅读了很多文章来处理这个问题,它们涉及添加更多我不理解的迭代级别。希望有人可以解释处理这个问题的正确方法,很多人都遇到了。

4

2 回答 2

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...
};
于 2013-10-29T19:01:28.787 回答
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 循环在调用 done(); 之前已经完成。

于 2013-10-29T19:08:54.367 回答