Promise.then()不会在第一次按钮点击时工作

时间:2017-10-09 01:58:11

标签: javascript promise es6-promise

我遇到的问题是当我点击" NewQuoteButton"在第一次加载页面时,我收到错误:quoteGenerator.getQuote(...).then is not a function。但是,如果我再次点击该按钮,我就能正常生成报价。此外,在检查我的Chrome检查器中的网络选项卡时,我注意到我有更多来自API的请求和响应,而我正在显示的报价滞后。

我是Promises的新手,目前正在练习利用它以及揭示模块模式。我的理解是Promise调用then(),它接受一个函数,将已解析的promise的值作为参数。因此,我的getQuote()应该工作,因为它返回一个包含引用对象的Promise。有人能指出我正确的方向。谢谢!

const quoteGenerator = (function(){
  let url = "https://andruxnet-random-famous-quotes.p.mashape.com/?cat=famous";
  let apiHeader = new Headers({
    "X-Mashape-Key": "..."
  });
  let init = {
    headers : apiHeader,
  }
  let quoteInfo = {};

  let getQuote = function(){
    fetch(url, init)
      .then(response => {
        if (response.ok){
          return response.json();
        }
        throw new Error("Get request failed");
        }, networkError => console.log("Error: " + networkError))
      .then(jsonResponse => {
        quoteInfo = Promise.resolve({
          quote: jsonResponse.quote,
          author: jsonResponse.author
        }); 
       });
      return quoteInfo;   
  };


  return {
    getQuote : getQuote
  };

})();

//Triggers when user clicks on social media button to share quote.
//Checks to see if quote has been generated from quoteGenerator before
//sharing it, if not, then button does nothing.

const clickHandler = (function(){
  let triggerClicked = function(){
    $("#twitter").on("click", function(e){
      e.preventDefault();
      window.open("https://twitter.com/intent/tweet?text=asdf");
    });

    $("#newQuoteButton").on("click", function(e){
        //ERROR BELOW//
        quoteGenerator.getQuote().then(function(quoteInfo){
        //ERROR ABOVE//
        $("#quoteSection > h2").html("<i class='fa fa-quote-left'></i>" + 
                                     quoteInfo.quote + "<i class='fa fa-quote-right'></i>");
        $("#author").html("<i>- " + quoteInfo.author + "</i>");
      }).catch(function(e){
        console.log(e);
      });
    });
  };
  return {
    handleClicks: triggerClicked
  }
})();

clickHandler.handleClicks();

2 个答案:

答案 0 :(得分:4)

返回Promise链中的数据,并按照@nnnnnn

的指示
  

getQuote()返回quoteInfo。它第一次被称为   承诺尚未完成,因此quoteInfo仍为空{}   对象它被初始化为。

quoteInfo可以从代码中省略

let getQuote = function() {
    return fetch(url, init)
      .then(response => {
        if (response.ok){
          return response.json();
        }
        throw new Error("Get request failed");
        }, networkError => console.log("Error: " + networkError))
      .then(jsonResponse => {
        return {
          quote: jsonResponse.quote,
          author: jsonResponse.author
        }; 
       });  
  };

  $("#newQuoteButton").on("click", function(e){
    //ERROR BELOW//
    quoteGenerator.getQuote().then(function(quoteInfo){
    //ERROR ABOVE//
    $("#quoteSection > h2")
    .html("<i class='fa fa-quote-left'></i>" 
    + quoteInfo.quote + "<i class='fa fa-quote-right'></i>");
    $("#author").html("<i>- " + quoteInfo.author + "</i>");
    }).catch(function(e){
      console.log(e);
    });
  });

答案 1 :(得分:2)

您需要返回提取呼叫

let getQuote = function(){
    return fetch(url, init)   // <<<<<<< use 'return'
      .then(resp => {
       return resp.ok ? resp.json() : Promise.reject(Error('Get request failed'));
      })
      .catch(networkError => {
       console.error('Error: ' + networkError);
       return Promise.reject(networkError); // <<<< have to call reject here, or throw
      })
      .then(jsonResponse => {
        return {
          quote: jsonResponse.quote,
          author: jsonResponse.author
        }; 
      });
  };

动态输入FTW:)

4个提示:

  1. 使用console.error而不是console.log来处理错误,因为这会写入stderr而不是stdout

  2. 使用单引号 - 它们更容易阅读IMO

  3. Promise catch块通常比使用“err-backs”更清洁,IMO

  4. 为您的错误使用真正的错误对象,而不仅仅是消息,否则将难以追踪。您不需要new关键字,只需调用Error()。