2017-02-26 10 views
0

私は文章を取り、略語をデータベースから完全なものに置き換えるプログラムを書いています(例えば、 "hiとgm" - > "hello and good morning" ifデータベースに格納されている略語は、 "hi" - > "hello"と "gm" - > "good morning")です。元の文は$( '#translation').text()に格納されており、それに応じて置き換えてください。約束のForループを実行する

私は、forループが約束を使用して各単語のヘルパー関数getFullWord()を完了するまで、getFullSentence()を待機させる方法を見つけました。

問題は、getFullWord()が順番に実行されていないことです。私が "i"を記録すると、0,1,2,3の代わりに0,3,1,2が得られます。どうすればこの問題を解決できますか?前もって感謝します!

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(); 
} 
+0

'$ .Deferred()' 'getFullWord()'関数、 'の.done(で必要はありません) 'はjQuery約束オブジェクトを返します。 'i'は' getFullWord'では使用されません。質問に「遊び」のテキストを含めることができますか? 'getFullSentence'から値が返されないのはなぜですか? '$ .get()'コールバックと '.done()'の代わりに '.then()'を '$ .get()'に連結して使用してください – guest271314

+0

ありがとうございました! play()はResponsiveVoice.jsというライブラリを呼び出して、その文を話します。 getFullSentence()はplay()関数を呼び出すだけで何も返す必要はありません – sleepycow

答えて

1

ここには多くの問題があります。まず、操作を順番に実行する必要はありません(あなたが思っているように思えます)。それらを並行して実行し、$.when()が順番に結果を収集するようにすることができます。これは、すべての結果を収集した後で最後にすべての処理を行い、$.when()がそれらを順番に収集することを要求します。

第2に、既に約束を返すものの周りに約束事を作成する場合に、延期防止パターンを使用しています。あなたは新しいものを作成するのではなく、$.ajax()から約束を直接返すことができます。

他のいくつかの改善点:

  • あなたが.each().push()を置き換えるために.map()を使用することができます。
  • .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(); 
    }); 
} 
関連する問題