Twitch API Let vs Var

Hi, I have been working on implementing a for loop for my Twitch Streamers app so that I can allow users to add streamers they like into the array with the streamers’ names and have those streamers automatically displayed.

To do this, I put strings (the streamers’ names) in an array through two different ajax calls. Divs are then created with ids of the name of string and include data about what twitch streamers are streaming from the ajax requests.

I was struggling to make it so that the element/streamer name would go through the first ajax call and then goes through the second because ajax calls are asynchronous. As a result, elements in the array would go through the second ajax request before the first one was completed and try to go into divs that were not yet created.

To try to fix this, I put the second ajax request within the first one like so:

ajax request{

code that makes divs

second ajax request}

This seems to have made the elements in the array come back in the correct order, but the divs were still not displaying the data from the ajax requests correctly. I noticed that when logging the name variable, that only one element in the array seemed to get passed through to the second ajax request.

Below is the old JS:

$(document).ready(function() {
  var twichUrl = "https://wind-bow.glitch.me/twitch-api";
  var channels = ["ESL_SC2", "freecodecamp", "OgamingSC2"];
  var name = "";
  var name2 = "";
  var logo = "";

  for (i = 0; i < channels.length; i++) {
    twitchUrl =
      "https://wind-bow.glitch.me/twitch-api/channels/" +
      channels[i] +
      "?callback=?";

    twitchUrlStream =
      "https://wind-bow.glitch.me/twitch-api/streams/" +
      channels[i] +
      "?callback=?";

    $.ajax({
      type: "GET",
      url: twitchUrl,
      dataType: "jsonp",
      jsonp: "callback",
      success: function(data) {
        name = data.display_name;
        logo = data.logo;
        console.log('channel data below:')
        console.log(name);


        $("body").append(
          "<div id=" +
          name +
          "Container>" +
          ' <span class ="icon" id =' +
          name +
          "><img src=" +
          data.logo +
          ">" +
          "</span>" +
          '<span class = "status" id = "' +
          name +
          'data"></span>' +
          "</div>"
        );
        $.ajax({
          type: "GET",
          url: twitchUrlStream,
          dataType: "jsonp",
          jsonp: "callback",
          success: function(data) {
            console.log('stream data below:')

            console.log(name);

            if (data.stream === null) {
              $("#" + name + "data").html( 
                " " + 
                '<a target = "_blank" href ="https://www.twitch.tv/' +
                name +
                '">' +
                name +
                "</a>" +
                " is currently offline"
              );
            } else {
              $("#" + name + "data").html(
                " " +
                '<a target = "_blank" href ="https://www.twitch.tv/' +
                data.stream.channel.display_name +
                '">' +
                data.stream.channel.display_name +
                "</a>" +
                " is Streaming: " +
                data.stream.game +
                "-- " +
                data.stream.channel.status
              );
            }
          }
        });
      }
    });
  }
});

However, I got some help and made two changes:

  1. I defined the ‘twitchUrlStream’, ‘twitchUrl’, ‘logo’, and ‘name’ variables with “let” rather than var.
  2. I defined ‘logo’ and ‘name’ within the for loop.

Here is the codepen now: https://codepen.io/mso122591/pen/jxNoBV

The problem is that I don’t understand much about var vs let and why this change seems to have fixed everything. The person said that using let creates a local variable, but more details/explanation would be great. Was var vs let truly the problem? Could I have solved this by keeping this variables defined as var?

My understanding is you have const, let, and var. They are all the same thing. However,
const - Is very specific and won’t be changed like:
const twichUrl = "https://wind-bow.glitch.me/twitch-api";

let - Is less specific and may change or is used in current code block like:
let apiCall = twichUrl + channels[i] + "?callback=?";

var - very generic and nothing special.

Even with the above you could just use any like if you use const you can still change the value it stores. So it is best to be consistent in your code like use const when it won’t change. Use let to be more specific for variables in a code block and use var less often.

Like what I have been doing is only using var in for loops.

Side note you could make another variable called apiCall like I did above that way you are not repeating the same twitch url that never changes.

More accurately:

var - the “old” declaration of a variable. It has function wide scope.

In ES6 we also have:

let - this is like var but has block level scope (less scope)

const - these are for constants, things that will never change. Teachnically they cannot be reassigned. For a primitive type that means that they cannot be changed. For non-primitives, they can be changed, but the variable cannot be reassigned.

At the heart of this is understanding scope and mutability.

1 Like

I would say that let and const are more common nowadays as limiting scope is good coding practice and as is being aware of mutability.

I never knew they actually acted different thanks for explaining better.

Thanks for the help!

I have been playing around with the variables, but cannot seem to make my project work if I define all the variables with “var”.

Is this to be expected or is it possible to make it work while using var? Specifically the ‘twitchUrlStream’, ‘twitchUrl’, ‘logo’, and ‘name’ variables. They seem to only work if I use “let”.

I would have have to see the before and after code, but since all your variables are declared globally, it shouldn’t matter whether you use let or var.

In the current version of your pen, I see:

$(document).ready(function() {
  var twichUrl = "https://wind-bow.glitch.me/twitch-api";
  var channels = ["ESL_SC2", "freecodecamp", "OgamingSC2"];
  
  for (i = 0; i < channels.length; i++) {
  let name = "";
  let name2 = "";
  let logo = "";
    
  let  twitchUrl =
      "https://wind-bow.glitch.me/twitch-api/channels/" +
      channels[i] +
      "?callback=?";
  // ...

In this example you’ve declared twitchUrl is declared twice. First you declare it in global scope with var and then inside the block of the for loop with the let. Now you have two versions of the same variable. Inside the for loop, the second one will have priority.

Some of this is hidden by your lack of proper indentation. Select all of your JS pane and do shft-tab - that will auto indent. Proper indenting will help you keep track of scope.

Thanks! I got rid of the first twitchUrl both my new version and old. Here is what the old version was like: https://codepen.io/mso122591/pen/MGaGOP

It seems like when using var, scope lasts for the duration of the function, so I thought that moving the declarations to the first ajax success would keep them contained within that scope/function, but that did not work so I am curious to see what it would look like to properly us var.