以正确的顺序执行一个For Loop循环

时间:2017-02-26 23:38:48

标签: javascript jquery get promise deferred

我正在编写一个程序,它接受一个句子并用数据库中的完整术语替换缩写(例如,“hi and gm” - >“hello and good morning”如果存储在数据库中的缩写是“hi” - >“你好”和“gm” - >“早上好”)。原始句子存储在$('#translation')。text()中,应该相应替换。

所以我发现如何让getFullSentence()等到for循环使用promises为每个单词完成辅助函数getFullWord()。

问题是getFullWord()没有按顺序执行,例如如果我记录“我”我得到0,3,1,2而不是0,1,2,3。我该如何解决这个问题?提前谢谢!

function getFullSentence(uid, sentence) {
    var promises = [];

    var words = sentence.split(" ");
    $.each(words, function(i, word) {
        promises.push(getFullWord(uid, word, i));
    });

    $.when.apply(null, promises).done(function() { 
        play($('#translation').text());
    });
}

function getFullWord(uid, word, i) {
    var defer = $.Deferred();

    $.get("/checkAbbreviation/" + uid + "/" + word, function(data) {
        word = data.full;

        var currSentence = $('#translation').text() + " ";
        var newSentence = currSentence + word.toUpperCase();
        $('#translation').text(newSentence);    
    }).done(function() {
        defer.resolve();
    });

    return defer.promise();
}

1 个答案:

答案 0 :(得分:1)

这里有很多错误。首先,您不需要按顺序运行您的操作(就像您认为的那样)。您可以并行运行它们,让$.when()按顺序收集结果。这只需要您在收集完所有结果后在最后完成所有处理,$.when()将为您收集它们。

其次,您正在使用延迟反模式,您可以在已经返回承诺的事物周围创建承诺。您可以直接从$.ajax()返回承诺,而不是创建新承诺。

其他一些改进:

  • 您可以使用.map()替换.each().push()
  • 您可以使用.join()加入所有字符串。
  • 如果您从.then()上的$.ajax()处理程序返回值,则会极大地简化$.when()中处理结果的过程。在这种情况下,您仍然希望返回data.full.toUpperCase()
  • 仅使用.then(),而不是.done()
  • 使用$.ajax()不要混合回调和承诺。使用其中一种(承诺可能是最好的)。

这是一种并行运行操作并按顺序收集结果的方法:

function getFullSentence(uid, sentence) {
    var promises = sentence.split(" ").map(function(word, i) {
        return getFullWord(uid, word, i);
    });

    $.when.apply($, promises).then(function() { 
        // get all results into an array
        var results = Array.prototype.slice.call(arguments);
        var text = results.join(" ");
        $('#translation').text(text);
        play(text);
    });
}

function getFullWord(uid, word, i) {
    return $.get("/checkAbbreviation/" + uid + "/" + word).then(function(data) {
        // make resolved value be data.full
        return data.full.toUpperCase();
    });
}