Skip to content Skip to sidebar Skip to footer

Code Inside While Loop Not Being Executed Javascript

I am working with this while loop and it is not working. I decided to use the Google Chrome debugger and I saw that the code inside is not being executed. All the time it checks th

Solution 1:

This question is best understood by understanding how node.js uses an event loop. At its core, node.js runs your Javascript in a single thread and it uses an event loop in order to manage the completion of things outside that single thread such as timers, network operations, file operations, etc...

Let's first start with a very simple while() loop:

let done = false;

setTimeout(() => {
    done = true;
}, 100);

while(!done) {
     // do whatever you want here
}
console.log("done with while loop");    // never gets called

At first blush, you would think that the while loop would run for 100ms and then done would be set to true and the while loop would exit. That is not what happens. In fact, this is an infinite while loop. It runs and runs and runs and the variable done is never set to true. The console.log() at the end never runs.

It has this issue because setTimeout() is an asynchronous operation and it communicates its completion through the event loop. But, as we described above, node.js runs its Javascript as single threaded and only gets the next event from the event loop when that single thread finishes what it's doing. But, the while can't finish what it's doing until done gets set to true, but done can't get set to true until the while loop finishes. It's a stand-off and the while loop just runs forever.

So, in a nutshell, while any sort of loop is running, NO asynchronous operation ever gets its result processed (unless it's using await inside the loop which is something different). Asynchronous operations (or anything that uses the event loop) has to wait until the current running Javascript is done and then the interpreter can go back to the event loop.


Your while loop has the exact same issue. spotifyApi.searchTracks() is an asynchronous operation that returns a promise and all promises communicate their results via the event queue. So, you have the same standoff. Your .then() handler can't get called until the while loop finishes, but your while loop can't finish until the .then() handler gets called. Your while loop will just loop infinitely until you exhaust some system resource and your .then() handlers never get a chance to execute.


Since you haven't included code in your request handler that actually produces some result or action (all it appears to do is just modify some local variables), it's not obvious what exactly you're trying to accomplish and thus how to better write this code.

You appear to have N searches to do and you're logging something in each search. You could do them all in parallel and just use Promise.all() to track when they are all done (no while loop at all). Or, you can sequence them so you run one, get its result, then run another. Your question doesn't give us enough info to know what the best option would be.

Here's one possible solution:

Sequence the operations using async/await

Here the request handler is declared async so we can use await inside the while loop. That will suspend the while loop and allow other events to process while waiting for the promise to resolve.

app.get('/process', ensureAuthenticated, asyncfunction (req, res) {
  let init_array = text.split(" ");
  let modtext = init_array;

  while (init_array.length != 0) {
    try {
      let data = await spotifyApi.searchTracks(modtext.join(" "));
      console.log(data.body.tracks.items[0].name);
      for (let i = 0; i < modtext.length; i++) {
        init_array.shift();
      }
      modtext = init_array;
    } catch (err) {
      console.log("No song");
      modtext.pop();
    }
  }
  res.redirect('/');
});

Solution 2:

The reason you're only seeing one line execute is because it's asynchronous. When you call an asynchronous function, it returns immediately and continues to do its work in the background. Once it's done, it calls another function (a "callback") and passes the results of the function to that. That's why your code has to go inside of a call to then() rather than just being on the next line of code.

In this case, spotifyApi.searchTracks() returns a Promise. Once the Spotify API has completed the search, the function in then() will run.

Solution 3:

Lets use async/await to solve this problem, I have no clue what data you get in a text but I think it is good example to understand a concept of asynchronous processing.

app.get('/process', ensureAuthenticated, asyncfunction (req, res, next) {
  try {
    const modtext = text.split(" ");
    const promises = modtext.map(item => spotify.searchTracks(item));
    const response = awaitPromise.all(promises);

    response.forEach(data => {
       // if you use lodash, simply use a get function `get(data, 'body.tracks.items[0].name')` => no need to check existence of inner attributes// or use something like thisif (data && data.body && data.body.track && data.body.tracks.items && data.body.tracks.items[0]) {
          console.log(data.body.tracks.items[0].name);
       } else { 
          console.log('No song');
       }
    });

    res.redirect('/');
  } catch(err) {
     next(err)
  }
});

For me much simpler and cleaner code, again, i dont know what is structure of your text attribute and logic behind it, so maybe you will have to make some changes.

Post a Comment for "Code Inside While Loop Not Being Executed Javascript"