Twitch Viewer API - For Loop RANDOMLY iterating over elements

Hi guys, currently working on the Twitch Viewer challenge and I seem to be having a problem with my iterations in my for loop… Not sure if it is an API problem. Anyway here is teh codez:

const channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
const streamers = document.getElementById("streamers");

for(let i = 0; i < channels.length; i++) {
  let url = "https://api.twitch.tv/kraken/channels/" + channels[i] + "?client_id=t300383ams5iuxlej34gzwk11qjepn&stream_type=all&callback=?";

  function callback(data) {
    const a = document.createElement("a");
    const li = document.createElement("li");
    const span = document.createElement("span");
    const img = document.createElement("img");

    a.setAttribute("href", data.url)
    a.setAttribute("target", "blank");
    a.appendChild(li);
    img.setAttribute("src", data.logo);
    li.appendChild(img);
    span.textContent = data.display_name;
    li.appendChild(span);
    streamers.appendChild(a);
  }

  $.getJSON(url, callback);
}

Output is fine…
Example:

However whenever I refresh the page it lists them in a different order…
Example:

This is going to be problematic when I start filtering by who is online and offline… So my question is:

How can I ensure that the Twitch API loops over my hard-coded array as is?

Thanks,
James.

Someone else can correct me if I’m wrong, but I think the order is determined by the order the responses are received.

  1. Send the next request after previous has completed
  2. Defer execution for requests that are too soon
  3. Chain promises
  4. Use a new hotness: async function

I have no idea what you mean, sorry haha.

const channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
const streamers = document.getElementById("streamers");
let promise = Promise.resolve()

for (let i = 0; i < channels.length; i++) {
  let url = "https://api.twitch.tv/kraken/channels/" + channels[i] + "?client_id=t300383ams5iuxlej34gzwk11qjepn&stream_type=all&callback=?";
  const p = $.getJSON(url);
  promise = promise.then(x => p).then(callback)

}

function callback(data) {
  const a = document.createElement("a");
  const li = document.createElement("li");
  const span = document.createElement("span");
  const img = document.createElement("img");

  a.setAttribute("href", data.url)
  a.setAttribute("target", "blank");
  a.appendChild(li);
  img.setAttribute("src", data.logo);
  li.appendChild(img);
  span.textContent = data.display_name;
  li.appendChild(span);
  streamers.appendChild(a);
}

Hi marzelin,

Thanks for the reply. I have taken the time out to try and understand Promises for a few hours and it still doesn’t seem to click…Perhaps it’s the whole functional approach which is throwing me off :confused:

From what I have read, I am looking at a Promise like this:

  • It allows for asynchronous code; meaning other things can run in the background whilst that is happening.
  • Using ‘then’ allows for us to determine the order of execution

Syntactically, I’m just completely thrown off. A breakdown of what you have just done would be fantastic.

Thanks,
James.

Promises are containers for future values.
They are abstractions over time and monads. I don’t know who invented this but it is just mindblowing.

Your conclusions about promises are correct. Keep reading, you’ll eventually get it.

Maybe this code will be easier to digest:

const channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
const streamers = document.getElementById("streamers");

// converts names to urls
const url = (name) => "https://api.twitch.tv/kraken/channels/" + name + "?client_id=t300383ams5iuxlej34gzwk11qjepn&stream_type=all&callback=?";

// an array that stores promises that store data for each channel
// [ promise<ESL_SC2 data>, promise<OgamingSC2 data>, ...]
const promisedChannelsData = channels
  .map(url)
  .map( (url) => $.getJSON(url) )

Promise
  // when all request completed
  .all(promisedChannelsData) 
  // call callback on each of the channel data
  // ie callback(<ESL_SC2 data>)
  .then( (datas) => datas.map(callback) )

function callback(data) {
  const a = document.createElement("a");
  const li = document.createElement("li");
  const span = document.createElement("span");
  const img = document.createElement("img");

  a.setAttribute("href", data.url)
  a.setAttribute("target", "blank");
  a.appendChild(li);
  img.setAttribute("src", data.logo);
  li.appendChild(img);
  span.textContent = data.display_name;
  li.appendChild(span);
  streamers.appendChild(a);
}

Hi marzelin,

I finished the Twitch project! Thank you for your answers. I just wanted a bit of clarification on what exactly ‘x’ is doing in your first code segment that you provided:

promise = promise.then(x => p).then(callback);

From what I know about arrow functions, I assume x is the parameter? But what exactly is it? And how does it help when calling the getJSON(url) function?

Thanks,
James.