How to make loop of getJSON calls wait for each other

Project Link - https://codepen.io/tlannoye11/full/xrayma/

When I load the page or hit my refresh button, it sets off a for loop that calls getJSON once per iteration. However, because of the time it takes to return each of the JSON objects, the order of the results is randomized every time. Is there an easy way to prevent this from happening?

First of all, is random bad?

If it is, you could wait until they are all loaded to output. I would have my display function separate from my JSON calls. As each JSON call returns, I would check to see if all of them have finished. Once they have, then I’d call my display. You can put up some ā€œWaitā€¦ā€ message until then.

How do you wait for each one to finish inside of a loop?

You don’t. You have a for loop that calls your getJSON. In the callbacks, you keep a counter that gets indexed each time a getJSON back. All the data gets stored in an array. At the end of the callback you check the counter to see if all of the data is back. If it is, then you call your display function which loops through the array sorts if you want and displays the data. Of course, you could sort as you go if you place the data in the array in the order you want as you go.

@ksjazzguitar You lost me at ā€œcallbacksā€.

Then it’s a little odd that you mention them in your code:

  // Populate an array of getJSON callbacks.

In any case, callbacks are an extremely important element of JavaScript. For example, in a typical getJSON call,

$.getJSON("https://somesite.com", function (data) {
  // do stuff with the data
}

The callback function is the second parameter of the getJSON call. This is important because getJSON is asynchronous and it will wait to call the call back until after the getJSON call is done. This happens a lot in JavaScript because so much of it is asynchronous. The callback function can be anonymous (as above) or named.

An example from your code would be:

$("#addNewButton").on("click", function() {
  streamers.push($("#newChannelInput").val());
  displayChannel($("#newChannelInput").val());
});

The second parameter of the on function is an anonymous callback function (starting with function()) It is asynchronous because you never know when the click is going to come and it waits for the click to do the callback.

Seriously, this is an important part of JS, especially with anything that is asynchronous (a major feature in JS). If it’s not clear, you may want to spend a little time understanding it. There are plenty of web tutorials and youtube videos to help you through it.

1 Like

@ksjazzguitar After I read your first response, I tried googling a few things to get a better idea of what was going on, and it wasn’t helping.

@SkyC that sounds like a much simpler solution. I’ll give that a try today.

Hi @tlannoye11,

Like @ksjazzguitar said, callbacks are a fact of life in JS. Sooner or later you’re going to have to get to grips with them. I came to this realisation as I am writing my weather app. After days and days of searching the web for something I could clearly understand, I found the following YouTube tutorials indispensable.

I am at one with callbacks now :slight_smile:

I’ll try using ā€˜promise’ in my next project as this is apparently the preferred way to handle asynchronous data. Albeit callbacks are also acceptable.

Cheers
RockLobster7

OK, I’m back after a weekend away from this.

@ksjazzguitar: I think I was misinterpreting what you meant by ā€œcallbacksā€. Not sure why, but whatever. At any rate, my latest interpretation of what you mean is in the OP. I’ve managed to separate the getJSON calls from the display of information by waiting until after my loop finishes to go back and display all of the data I receive.

Unfortunately, I still haven’t managed to solve the original problem. I’m still unable to show consistent results in the same order that I looked for them. The problem now is that some JSON objects will have data in them, but others will just have an error because they don’t exist (like the ā€œbrunofinā€ example). I can’t use the suggestion from @SkyC because the error JSON doesn’t have a reference to the name of the stream that is causing the error.

How do I sort these JSON objects that might not all have the same information in them? Or, am I still missing something else?

OK, I think I got that part down. Now I’m just trying to handle the issue of a streamer with a name that is technically invalid Javascript. For example, there’s a sample stream named ā€œESL_SC2ā€.

Unfortunately, I still haven’t managed to solve the original problem. I’m still unable to show consistent results in the same order that I looked for them.

OK, I’ve been thinking about this. I’m still not sure why they have to be in the same order, but since you insist…

Instead of pushing the data into your array - meaning that it gets in there in any old order - why don’t you place it in the ā€œcorrectā€ slot. Instead of:

streamerData.push(data);

You would have:

streamerData[i]=data;

That way you’d know it is getting into the array in the right order. (Though your’re probably going to have to bind i).

You could also avoid the problem of a blank screen that way. Since you already know what order they will be in, you can put the names up first. Then you could even call your displayChannelData(data) as the data comes in because you know where it is all supposed to go.

There are so many different ways to approach this. I remember the Twitch project as being the most frustrating of the frontend projects for me. Don’t give up. It took me a couple of tries.

The problem now is that some JSON objects will have data in them, but others will just have an error because they don’t exist (like the ā€œbrunofinā€ example).

But that is part of the test. In real world coding, you have to account for things going wrong.


I would say one other thing if I may - I’m always amazed when I see people who have put all this effort in their CSS and layout and made everything all pretty and their still struggling with the core JS logic. To me all that other stuff is a distraction. It would be like building a car and spending all your time worrying about the windshield wipers before you’re even sure if the engine and drive train works. When I approach a problem like this, the first thing I do is work on the JS logic. Almost all of my outputting is to the console. For this project I would:

  1. Make sure I can get the data I want and can store it the way I need.

That’s it. That’s the first step. I don’t do anything else until I can do that. That is the toughest part of the whole thing. I would make sure the data loads in and make sure I understand what information is coming in and make sure it is being stored in the way that I want. That is job one.

Once that is done, then I’d start outputting it to the screen and start using CSS to make it pretty and inserting buttons and such and adding events.

If I were you, I might consider creating a new pen and just working on the JS logic until you understand it better. It will also be easier for people to help you if they don’t have to wade through a page of JQuery click handlers to get to the core of your code.

I’m sure there are people that disagree with my approach, but that’s what’s worked for me. Make sure the boat floats before you buy the paint and order the sails.

Just my $.02.

Hi @tlannoye11, I am surprised you’re still stumped by this:

The second video I provided details why the problem you are having exists and what to do about it.

I guess sometimes it’s just nicer if people just ā€˜hand us’ the answers on a platter.

RockLobster7