Twitch Viewer API - For Loop RANDOMLY iterating over elements

Twitch Viewer API - For Loop RANDOMLY iterating over elements
0

#1

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.


#2

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


#3
  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

#4

I have no idea what you mean, sorry haha.


#5
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);
}

#6

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.


#7

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);
}

#8

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.