JonX JonX - 2 months ago 6
Ajax Question

can't get the right index result with an ajax call

I was trying to iterate the 'streamers' array by the variable showindex but failed,it just shows the first element "monstercat" and last element "amazhs" of the array, using debug in chrome and showindex in the displayResult function always is 0 and 9, can't figure out why, any help? Thanks!



var streamers = ['monstercat', 'sivhd', 'cryaotic', 'nightblue3', 'picoca_lol', 'freecodecamp', 'trick2g', 'riotgamesbrazil', 'riotgames', 'amazhs'];
$(document).ready(function() {
var logo = "";
var channelName = "";
var showindex = 0;

streamers.forEach(function(streamer, index) {
showindex = index;
$.ajax({
type: 'GET',
jsonp: "callback",
url: 'https://api.twitch.tv/kraken/streams/' + streamer,
headers: {
'Client-ID': 'd50b88uvtwlhdfrqi3vj3k1hm3izkyx'
},
success: displayResult
});
});

function displayResult(data) {
var outstring = "";
if (data.stream !== null) {
channelName = data.stream.channel.display_name;
logo = data.stream.channel.logo;
} else {
logo = "https://placeholdit.imgix.net/~text?txtsize=6&txt=50%C3%9750&w=50&h=50";
channelName = streamers[showindex];
}
outstring +=
"<li class='streamer'>" +
"<img class='streamer-icon' src='" + logo + "'/>" +
"<p class='streamer-name'>" +
"<a href='http://twitch.tv/" + channelName + "' target='_blank'>" + channelName + "</a></p>" +
"<span class='streamer-status'>" +
"<i class='fa fa-exclamation'></i></span></li>"
$("#showBox").append(outstring);
}
});

ul {
padding: 0;
margin: 0;
}

.tab-content {
border: 1px solid #ddd;
border-top: none;
}

.streamer {
list-style-type: none;
padding: 10px;
}

.streamer-icon {
width: 50px;
}

.streamer-name {
display: inline-block;
margin-left: 10px;
}

.streamer-status {
float: right;
padding-top: 15px;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="row col-md-4 col-md-offset-4">
<ul class="nav nav-tabs" role="tablist">
<li class="active"><a href="#all" aria-controls="all" role="tab" data-toggle="tab">all</a>
</li>
<li><a href="#online" aria-controls="online" role="tab" data-toggle="tab">online</a>
</li>
<li><a href="#offline" aria-controls="offline" role="tab" data-toggle="tab">offline</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="all">
<ul id="showBox">
</ul>
</div>
<div class="tab-pane" id="online">
<ul></ul>
</div>
<div class="tab-pane" id="offline">
<ul></ul>
</div>
</div>
</div>
</div>




Answer

It's because the calls are all happening at the same time so instantly showindex = 9 a way around this would be to do the incrementation in displayResult though it could still go wrong (but it's less likely).

You probably could change your code entirely to make it use promises which would be a lot safer.

var streamers = ['monstercat', 'sivhd', 'cryaotic', 'nightblue3', 'picoca_lol', 'freecodecamp', 'trick2g', 'riotgamesbrazil', 'riotgames', 'amazhs'];
$(document).ready(function() {
  var logo = "";
  var channelName = "";
  var showindex = 0;

  streamers.forEach(function(streamer, index) {
    $.ajax({
      type: 'GET',
      jsonp: "callback",
      url: 'https://api.twitch.tv/kraken/streams/' + streamer,
      headers: {
        'Client-ID': 'd50b88uvtwlhdfrqi3vj3k1hm3izkyx'
      },
      success: displayResult
    });
  });

  function displayResult(data) {
    var outstring = "";
    if (data.stream !== null) {
      channelName = data.stream.channel.display_name;
      logo = data.stream.channel.logo;
    } else {
      logo = "https://placeholdit.imgix.net/~text?txtsize=6&txt=50%C3%9750&w=50&h=50";
      channelName = streamers[showindex];
    }
    outstring +=
      "<li class='streamer'>" +
      "<img class='streamer-icon' src='" + logo + "'/>" +
      "<p class='streamer-name'>" +
      "<a href='http://twitch.tv/" + channelName + "' target='_blank'>" + channelName + "</a></p>" +
      "<span class='streamer-status'>" +
      "<i class='fa fa-exclamation'></i></span></li>"
    $("#showBox").append(outstring);
    showindex++;
  }
});
ul {
  padding: 0;
  margin: 0;
}
.tab-content {
  border: 1px solid #ddd;
  border-top: none;
}
.streamer {
  list-style-type: none;
  padding: 10px;
}
.streamer-icon {
  width: 50px;
}
.streamer-name {
  display: inline-block;
  margin-left: 10px;
}
.streamer-status {
  float: right;
  padding-top: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row col-md-4 col-md-offset-4">
    <ul class="nav nav-tabs" role="tablist">
      <li class="active"><a href="#all" aria-controls="all" role="tab" data-toggle="tab">all</a>
      </li>
      <li><a href="#online" aria-controls="online" role="tab" data-toggle="tab">online</a>
      </li>
      <li><a href="#offline" aria-controls="offline" role="tab" data-toggle="tab">offline</a>
      </li>
    </ul>
    <div class="tab-content">
      <div class="tab-pane active" id="all">
        <ul id="showBox">
        </ul>
      </div>
      <div class="tab-pane" id="online">
        <ul></ul>
      </div>
      <div class="tab-pane" id="offline">
        <ul></ul>
      </div>
    </div>
  </div>
</div>

Here's another way to do it, it doesn't use foreach but iterates through the array another way. This way is a bit slower but means it doesn't get ahead of itself (you can actually see each one pop in)

var streamers = ['monstercat', 'sivhd', 'cryaotic', 'nightblue3', 'picoca_lol', 'freecodecamp', 'trick2g', 'riotgamesbrazil', 'riotgames', 'amazhs'];
$(document).ready(function() {
  var logo = "";
  var channelName = "";
  var showindex = 0;

  //Work out if there are any streamers left in the array
  function calcStreamers() {
    if (showindex < (streamers.length - 1)) {
      //if there are add 1 and go get it
      showindex++;
      streamersGet();
    } else {
      //if not just stop
      return false
    }
  };

  //The get function
  function streamersGet() {
    $.ajax({
      type: 'GET',
      jsonp: "callback",
      url: 'https://api.twitch.tv/kraken/streams/' + streamers[showindex],
      headers: {
        'Client-ID': 'd50b88uvtwlhdfrqi3vj3k1hm3izkyx'
      },
      success: displayResult
    });
  };

  function displayResult(data) {
    var outstring = "";
    if (data.stream !== null) {
      channelName = data.stream.channel.display_name;
      logo = data.stream.channel.logo;
    } else {
      logo = "https://placeholdit.imgix.net/~text?txtsize=6&txt=50%C3%9750&w=50&h=50";
      channelName = streamers[showindex];
    }
    outstring +=
      "<li class='streamer'>" +
      "<img class='streamer-icon' src='" + logo + "'/>" +
      "<p class='streamer-name'>" +
      "<a href='http://twitch.tv/" + channelName + "' target='_blank'>" + channelName + "</a></p>" +
      "<span class='streamer-status'>" +
      "<i class='fa fa-exclamation'></i></span></li>"
    $("#showBox").append(outstring);
    //Once the data has been added to the page go and check if there are more to add
    calcStreamers();
  }
  //Initally start by getting the first result
  streamersGet();
});
ul {
  padding: 0;
  margin: 0;
}
.tab-content {
  border: 1px solid #ddd;
  border-top: none;
}
.streamer {
  list-style-type: none;
  padding: 10px;
}
.streamer-icon {
  width: 50px;
}
.streamer-name {
  display: inline-block;
  margin-left: 10px;
}
.streamer-status {
  float: right;
  padding-top: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <div class="row col-md-4 col-md-offset-4">
    <ul class="nav nav-tabs" role="tablist">
      <li class="active"><a href="#all" aria-controls="all" role="tab" data-toggle="tab">all</a>
      </li>
      <li><a href="#online" aria-controls="online" role="tab" data-toggle="tab">online</a>
      </li>
      <li><a href="#offline" aria-controls="offline" role="tab" data-toggle="tab">offline</a>
      </li>
    </ul>
    <div class="tab-content">
      <div class="tab-pane active" id="all">
        <ul id="showBox">
        </ul>
      </div>
      <div class="tab-pane" id="online">
        <ul></ul>
      </div>
      <div class="tab-pane" id="offline">
        <ul></ul>
      </div>
    </div>
  </div>
</div>