1

I'm new to chaining JavaScript promises. I read all of the answers regarding above error. Added lots of return, but still, do not understand why it is returning undefined.

I have 3 getJson calls (user, logo and stream). Data from all three are colected in thisNameInfo array and used to build html.

In one of the prevous versions all then statments were chained in one signle line. That did not produce error, but the html was build before the getJson call was executed. After reading this thread how to chain then functions I added 3 call routines (callUser, callLogo and callStream).

It passes first callUser and gives me Cannot read property 'then' of undefined for 'then' after the callLogo. Point of error is underline in the code with ``````````````.

Thanks for help.

If you have suggestiong how to better pass data from getJson calls to function that build html I would love to hear it.

Here is my code:

var allStreamers = ["freecodecamp", "animeexpo", "brunofin"];

// build html for one stereamer
var buildStreamerHtml = function(thisNameInfo){
  //build html using thisNameInfo
  ... some code goes here
  $("#display").append(html);
};

// get user 
var user = function(name, thisNameInfo){  
  // return promise or "then" will return undefined!!!
  return $.getJSON(
      "https://wind-bow.glitch.me/twitch-api/users/" + name,
      function(data) {
        // if user does not exist data.error if 404 and data.message exist
        if (data.message) {
          thisNameInfo.userExist = "no";
          thisNameInfo.title = data.message;
          thisNameInfo.url = "#";
          thisNameInfo.logo = "";
        } else{
          thisNameInfo.userExist = "yes";
        }
      });     
};

// get logo, title and url
var logo = function(name, thisNameInfo){
  if (thisNameInfo.userExist === "yes"){
    // get logo and title with link to url    
    // return promise or "then" will return undefined!!!
    return $.getJSON("https://wind-bow.glitch.me/twitch-api/channels/" + name,    
            function(dataChannel) {
              thisNameInfo.url = dataChannel.url;
              thisNameInfo.title = dataChannel.display_name;
              thisNameLogo.logo = dataChannel.logo;
            });  
  } 
};

// get stream title and number of watchers
var stream = function(name, thisNameInfo){
  if (thisNameInfo.userExist === "yes"){
    // return promise or "then" will return undefined!!!
    return $.getJSON("https://wind-bow.glitch.me/twitch-api/streams/" + name,
            function(dataStreams) {
              if (dataStreams.stream) {
                thisNameLogo.status =   "Online";
                thisNameLogo.streamTitle =  dataStreams.stream.channel.status;
                thisNameLogo.viewers =  dataStreams.stream.viewers;
              } else {
                thisNameLogo.status =   "Offline";
              }
            });  
  }
};  

var callUser = function(name, thisNameInfo){
  return user(name, thisNameInfo).then(callLogo(name, thisNameInfo));
};

var callLogo = function(name, thisNameInfo){
  return logo(name, thisNameInfo).then(callStream(name, thisNameInfo));
};                                ``````````````````````````````````````

var callStream = function(name, thisNameInfo){
  return stream(name, thisNameInfo);
};

// link together all asinhronious calls for one streamer
var getStreamerInfo = function(name){
  "use strict";
  // this variable builds up by assinhronious calls 
  // then its value is usedd by buildStreamerHtml
  console.log("getStreamerInfo name: " + name);
  var thisNameInfo = {}; 
  callUser(name, thisNameInfo).then(buildStreamerHtml(thisNameInfo));
};

// loop through all streamers and display them
allStreamers.forEach(getStreamerInfo); 

The undefine points after the second promise callLogo

Ivana
  • 85
  • 6

1 Answers1

2

It looks like your issue could be that you are not passing callback functions to each then().

When you pass callLogo(name, thisNameInfo) to then(), you are actually calling the function immediately and passing it's return value:

return user(name, thisNameInfo).then(callLogo(name, thisNameInfo));

Instead, you need to pass a callback function that will be called once the Promise resolves:

return user(name, thisNameInfo).then(function() {
  callLogo(name, thisNameInfo)
});

You need to do this anytime you are using then().