Why does this linked list function not work?

I’m playing around with the Star Wars API to learn APIs. It’s a simple API without any authorization needed (which is good since I can never seem to get authorizations right, and docs aren’t written for newbs).

Anyway, I can make a simple request, for example to get planets:

fetch("https://swapi.dev/api/planets/?page=6")
        .then(response => response.json())
        .then(data => console.log(data))

This results in this:

count: 60
next: null
previous: "http://swapi.dev/api/planets/?page=5"
results: Array(10)
0: {name: "Mirial", rotation_period: "unknown", orbital_period: "unknown", diameter: "unknown", climate: "unknown", …}
1: {name: "Serenno", rotation_period: "unknown", orbital_period: "unknown", diameter: "unknown", climate: "unknown", …}
etc...

Now, the “next” property is important, because this is a linked list. This particular request is for page 6, which is the last one. The value for next here is null.

I’m trying to write a function that will start on page 1, read all 10 planets, push them to an array, and then use the next property to fetch that url (the next value is a url), and do that for six pages, until we get to this page, where the next is null.

I’m trying to do this in a while loop, while(url !== null). Unfortunately, something’s not working and it does an infinite loop.

Anyway, I’m stumped. What am I doing wrong? Full code below.

function getPlanets(apiUrl) {
    let url = apiUrl;
    while (url !== null) {
        fetch(url)
        .then(response => response.json())
        .then(data => {
            starArr.push(data.results);
            url = data.next;
        })
    }
    console.log("done");
}

getPlanets("http://swapi.dev/api/planets/");

That’s because JS fetch is async and it takes time before request is returned and url changes.

Here’s improved version of your code:

const starArr = [];

function getPlanets(apiUrl) {
  if (!apiUrl) {
    console.log('done');
    return;
  }

  fetch(apiUrl)
    .then((response) => response.json())
    .then((data) => {
      starArr.push(...data.results);

      console.log(starArr.length);
      console.log(data.next);

      getPlanets(data.next);
    });
}

getPlanets('https://swapi.dev/api/planets/');

Perfect, very nice code that works beautifully.

So the async nature of the code was causing the while statement’s control condition to never be satisfied?

In a perfect world of infinite memory and no API requests limit, the while statement would be satisfied eventually, but in reality you’ll either hit memory limit and browser will kill your script or your requests will get throttled/banned on the API side.