代码之家  ›  专栏  ›  技术社区  ›  Prosper

JQuery。when()和then()不处理异步事件

  •  0
  • Prosper  · 技术社区  · 8 年前

    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获得全局变量chosenWord的相同值?我不明白为什么when()和then()函数在我的代码中不起作用。

    1 回复  |  直到 8 年前
        1
  •  0
  •   jfriend00    8 年前

    你必须把承诺归还 wordFromFile() .

    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 值为承诺的解析值,则应从 .then() 处理程序。另外,请注意,我更改了您的回拨 $.get() .then() 处理程序使事情更加一致。通常,一旦您使用了承诺,您希望在操作中一致地使用它们,而不是在承诺中混合使用老式回调。这样做会破坏承诺提供的一些自动错误传播和错误处理功能。

    然后,您不需要使用 $.when() 完全 setRandomWord() 因为 wordFromFile() 已经返回了一个承诺,您需要将函数引用传递给 .then() 在附加词后没有parens:

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

    概括如下:

    1. wordFromFile()
    2. 使用 .then() 内部处理程序 wordFromFile() 而不是jQuery回调。
    3. $。当() wordFromFile() 因为它是不需要的。
    4. 删除后面的parens appendWord 将函数引用传递给 .then() .您的方式是立即调用appendWord,而不是允许 .then() 处理程序,以便稍后在承诺解析时调用它。
    5. 你的随机数逻辑不是很正确,除非你总是试图避免第一个词。

    记住,承诺没有魔力。它们不“知道”它们内部的异步操作何时完成。只有当异步操作手动解析承诺时,它们才知道异步操作何时完成。因此,您不能在 $。当() $。当() 神奇地知道异步操作何时完成(很多人都尝试过这一点,显然这是承诺新手似乎期待的)。相反,你将承诺传递给 $。当() 异步操作必须解析这些承诺。在您的情况下,您只有一个承诺,因此没有必要 $。当() .通常只有当你有一个以上的承诺要等待时才需要。当你只有一个承诺时,你可以打电话 .then() 在上面。

    其他需要注意的事项:

    1. 您使用的是全局变量 乔森沃德 以反馈结果。这是不必要的,通常被认为是反模式。
    2. 在ajax调用中没有任何错误处理。

    此代码:

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

    可以简化为:

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

    如果主体标记具有 playpage 类,然后它将调用 setRandomWord() 如果不是,它将不会调用它。


    您可以删除 乔森沃德

    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() 返回,因此它将传递给任何 .then() handler放弃了这个承诺。当你经过时 附言 作为一个 .then() handler,这意味着该词将被传递给 附言 为你。并且,wala不使用全局。