Ajax error call

I should be making an ajax call to the streams array for each element in it…
I seem to be getting a success call for just the 2 that have a stream value.
I’m trying to get anything for the other 6 in the streams array, their stream value is null. But why can’t I get that to log?
I thought I copied and pasted the error call from the success call and have tried several mutations. I thought I’d be able to show stream equals null… or at-least a console.log ('something');

The only thing to reach the error on the AJAX is when I change my client ID to xxx for posting here. Then they all go through the error.

I moved the functions outside of the for loop, because they were triggering the linter…

But I shuold still be able to show something for a stream, even when it’s inactive… even if it’s just null.

$(document).ready(function() {
  var streams = [
    "cretetion",
    "freecodecamp",
    "storbeck",
    "habathcx",
    "RobotCaleb",
    "noobs2ninjas",
    "gamesdonequick",
    "OgamingSC2"
  ];

  //helper function, on success
  function dada(dataI) {
    console.log("dada name", dataI.stream.channel.name);
    console.log("dada status", dataI.streams);
    console.log("dada links", dataI._links);
    console.log("dada game", dataI.stream.channel.game);
  }

  //helper function, on error
  function dadone(dataf) {
    console.log("dadone name", dataf.stream.channel.name);
    console.log("dadone status", dataf.stream[i]);
    console.log("dadone links", dataf._links);
    console.log("dadone game", dataf.stream.channel.game);
    //console.log("dadone game", dataI.stream.channel.game);
  }

  for (var i = 0; i < streams.length; i++) {
    $.ajax({
      type: "GET",
      url: "https://api.twitch.tv/kraken/streams/" + streams[i],
      headers: {
        "client-ID": "xxxxxxxxxxxx"
      }, //end of header
      success: dada,
      error: dadone,
    }); //end of ajax call
  } //end of for loop from  stream's length
}); //$(document).ready(function()

It’s like it’s skipping over 6 entries in the array…
This is the json object for one of the null streams

Due to the asynchronous nature of $.ajax() you cannot call it within a for loop like that, and rely on the value of i incrementing with each call.

for (var i = 0; i < streams.length; i++) {
  $.ajax({
    ...
  });
}

I’m a bit pushed for time right now, but this SO thread explains the problem and solution.

Try that and let us know if you get stuck.

1 Like

I think you’ve put me on the right track… my first thought was to increment in the sub functions, and I may still try that just to see what happens. I’m assuming json or ajax are both going to behave in the same way… ajax is just jquery for jason right? After I kept reading, it sounds like .forEach might be what I need here.

Hi,

JSON is a data format.
$.ajax() is jQuery’s way of making an Ajax call.
$.getJSON does what the name suggests, but uses $.ajax under the hood.

I might be getting closer, i is maintaing it’s scope all the way through the loop now… each index from the array is showing up, But it seems to be triggering both a success and error call for each and then ending with an array of everything undefined… why would it be calling both? and how do I access the objects I’m getting back?

var streams = [
  "summit1g",
  "ESL_SC2",
  "cretetion",
  "storbeck",
  "habathcx",
  "RobotCaleb",
  "noobs2ninjas",
  "gamesdonequick",
  "OgamingSC2",
  "freecodecamp"
];
//jquery run
$(document).ready(function() {
  function twatch(i) {
    $.ajax({
      type: "GET",
      url: "https://api.twitch.tv/kraken/streams/" + i,
      headers: {
        "client-ID": "xxx"
      }, //end of header
      success: console.log("success", i),
      error: console.log("error", i)
    }); //end of ajax call
  } //end of twatch
  
  var funcs = [];

  for (let i = 0; i < streams.length; i += 1) {
  funcs[i] = twatch(streams[i]);
    console.log(i);
  }
  console.log(funcs);
}); //end of $(document).ready(function()
/*
https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example/41023816#41023816
for (var i = 0; i < streams.length; i++) {
*/

https://codepen.io/TurtleWolf/pen/KqryPg?editors=0012

You can’t assign the result of an async operation to a variable like this. One way to accomplish what you want would be to declare the array in the upper scope, then push values to it from within the success callback.

const funcs = [];

function twatch(i) {
  $.ajax({
    type: "GET",
    url: `https://api.twitch.tv/kraken/streams/${i}`,
    headers: { "client-ID": "xxx" },
    success: (res) => { funcs.push(res) },
    error: (err) => { console.log(err) }
  });
}

for (let i = 0; i < streams.length; i += 1) {
  twatch(streams[i]);
}

AFAIK, you need to pass the success property a function for it to call. Try changing:

success: console.log("success", i),
error: console.log("error", i)

to:

success: (res) => { console.log(res) },
error: (err) => { console.log(err) }
1 Like

Thank you, that makes sense… I had to look up Afaik, but now that makes 3 things I learned from your reply.

No worries :slight_smile: I’d be interested to hear how you get on.

Mind that this does so when the AJAX resolves. That means that after making the AJAX call, the array will still be empty.

1 Like

Does that mean the information I want is coming back, I’m just not seeing it? Like if I just waited twenty seconds and refreshed my tags from local variables with out making any new calls.
They are probably just sitting there after I’ve made the console log calls already… ?
so I’m logging to the console before the ajax has a chance to finish?

Once you do something asynchronously (like AJAX) you can’t go back to synchronous code processing (what you normally do in JS). This means that you need to do anything you want to do (with the asynchronous values) in callbacks that get triggered when the asynchronous process is done.

in your case that means that you would have to do all the processing in the success callback.

1 Like

Yup. Good point. Something like:

const funcs = [];

$.when(
  // Do ajax
).then( () => {
  console.log(funcs);
});

should work.

1 Like

or since jQuery AJAX is Promise-like:

$.ajax(/* ... */).done( fn );
1 Like

Yeah, but the OP is making multiple $.ajax calls using a for loop, so that’d negate the point of using a loop and be quite verbose. Or am I missing something?

1 Like

Ah, missed that one. Then he could use Promise.all().

2 Likes

You’ve given me the proper syntax to start working on this again… I’m getting back 9 null streams and one that is live, but most importantly I’m seeing a return for either and for everything, and now I have a template to understand the format better.
I’ve heard all of these key words thrown about on pod cast for years, but have not had to deal with them directly. I feel this is a game changer, like I am both leveling up and facing a whole new can of worms…

1 Like

That’s good to hear. JavaScript’s async nature can be a bit tricky to get your head round at first, but if you persevere, it goes “click” at some point.

If you’d like to find out more, I can suggest this video. It’s really enlightening:

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.