2017-02-26 97 views
0

我正在編寫一個程序,它接受一個句子,並用數據庫中的完整詞彙替換縮寫(例如,「你好,gm」 - >「你好,早上好」if存儲在數據庫中的縮寫是「hi」 - >「hello」和「gm」 - >「早上好」)。原始語句存儲在$('#translation')。text()中,並且應該相應地替換。以正確的順序執行承諾循環

因此,我發現如何使getFullSentence()等待for循環通過使用promise來爲每個單詞完成助手函數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(); 
} 
+0

'$ .Deferred()'是沒有必要的'getFullWord()'函數,'.done( )'返回一個jQuery承諾對象。 '我'不用'getFullWord'。你可以在問題中包含「play」文字嗎?爲什麼沒有從'getFullSentence'返回值?使用'.then()'鏈接到'$ .get()'而不是'$ .get()'callback和'.done()' – guest271314

+0

感謝您的迴應! play()調用一個名爲ResponsiveVoice.js的庫來說出這個句子。 getFullSentence()不需要返回任何東西,因爲它只是調用play()函數 – sleepycow

回答

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