簡體   English   中英

JQuery.when()和then()不適用於異步事件

[英]JQuery.when() and then() not working with asynchronous event

我正在嘗試從文本文件中讀取行,從文件中選擇一行並將其插入html頁面上的div。

var chosenWord="original word";

function wordFromFile(fileName) {
    $.get(fileName, function(data) {
        var lines = data.split("\n");
        var lineCount = lines.length;
        var randomIndex = Math.floor(Math.random() * ((lineCount-1) + 1));
        var word = lines[randomIndex];
        window.chosenWord = word;
        console.log("wordFromFile: "+chosenWord);
    });
}

function setRandomWord() {
  $.when(wordFromFile("http://mypage.com/words.txt")).then(appendWord());
}

function appendWord() {
  console.log("appendWord: "+window.chosenWord);
  $('.word').text(window.chosenWord);
}

$(function() {
  if($('body').is('.playpage')) {
    setRandomWord();
  }

});


console shows:
appendWord: original word
wordFromFile: particle //when i refresh the page this word changes but appendWord is always "original word"

我怎樣才能使wordFromFile(fileName)函數首先完成,並且appendWord為全局變量selectedWord獲取相同的值? 我不明白為什么when()和then()函數在我的代碼中不起作用。

您必須在wordFromFile()返回promise。

function wordFromFile(fileName) {
    return $.get(fileName).then(function(data) {
        var lines = data.split("\n");
        var lineCount = lines.length;
        var randomIndex = Math.floor(Math.random() * lineCount);
        var word = lines[randomIndex];
        window.chosenWord = word;
        console.log("wordFromFile: "+chosenWord);
        return chosenWord;
    });
}

而且,如果您希望最終的chosenWord值是promise的已解析值,則應從.then()處理程序中返回它。 另外,請注意,我將$.get()上的回調更改為.then()處理程序,以使事情更加一致。 通常,一旦使用了promise,就希望在一個操作中一致地使用它們,而不是在promise中混合使用老式的回調。 這樣做會破壞承諾提供的某些自動錯誤傳播和錯誤處理功能。

然后,您完全不需要在setRandomWord()使用$.when() setRandomWord()因為wordFromFile()已經返回了一個wordFromFile()並且您需要在appendWord之后將函數引用傳遞給.then .then()而不使用括號:

function setRandomWord() {
  wordFromFile("http://mypage.com/words.txt").then(appendWord);
}

回顧一下:

  1. wordFromFile()返回承諾
  2. wordFromFile()中使用wordFromFile() .then()處理函數,而不要使用jQuery回調。
  3. 刪除wordFromFile() $.when()周圍的$.when() wordFromFile()因為它不是必需的。
  4. 將函數引用傳遞給appendWord .then()時,請在appendWord之后刪除括號。 您所擁有的方式是立即調用appendWord,而不是在promise解決之后的某個時間允許.then .then()處理程序調用它。
  5. 除非您一直試圖避免使用第一個單詞,否則您的隨機數邏輯不太正確。

請記住,諾言沒有魔力。 當它們內部的異步操作以某種方式完成時,它們不“知道”。 他們僅在異步操作手動解決承諾時知道異步操作何時完成。 因此,您不能只是在$.when()放入一些異步操作,並期望$.when()神奇地知道何時完成異步操作(很多人都嘗試過這一點,顯然這是人們初次嘗試的事情似乎可以預期)。 相反,您將承諾傳遞給$.when() ,異步操作必須解析這些承諾。 在您的情況下,您只有一個承諾,因此不需要$.when() 通常只有在您有多個希望等待的諾言時才需要使用它。 當您只有一個承諾時,就可以在其上調用.then()

其他注意事項:

  1. 您正在使用全局變量chosenWord傳遞回結果。 這不是必需的,通常被認為是反模式。
  2. 您的ajax調用沒有任何錯誤處理。

這段代碼:

$(function() {
  if($('body').is('.playpage')) {
    setRandomWord();
  }

});

可以簡化為:

$(function() {
  $("body.playpage").each(setRandomWord);
});

如果body標簽上具有playpage類,則它將調用setRandomWord() 如果沒有,它將不會調用它。


您可以像這樣從代碼中刪除chosenWord全局chosenWord

function wordFromFile(fileName) {
    return $.get(fileName).then(function(data) {
        var lines = data.split("\n");
        var randomIndex = Math.floor(Math.random() * lines.length);
        var word = lines[randomIndex];
        console.log("wordFromFile: "+word);
        return word;
    });
}


function setRandomWord() {
  return wordFromFile("http://mypage.com/words.txt")).then(appendWord);
}

function appendWord(word) {
  console.log("appendWord: "+word);
  $('.word').text(word);
}

$(function() {
  $("body.playpage").each(setRandomWord);
});  

在這里,選定的單詞成為wordFromFile()返回的promise的解析值,因此它將被傳遞給該promise之外的任何.then()處理函數。 當您將appendWord作為appendWord .then()處理函數傳遞時,這意味着該單詞將為您傳遞給appendWord 而且,wala不使用全局變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM