-4

I currently have a very simple for loop running, but it is getting details from a database so involves some delay. It's a very basic script so doesn't involve a lot of extra code shown in other questions.

var animals = ['dog', 'cat', 'fish', 'squirrel'];
for (var x in animals) {
  console.log('Animal ' + (Number(x) + 1) + ' is a ' + animals[x]);
}
console.log('loop is finished!');

Of course, if you run this usually, you get the expected log, of

"Animal 1 is a dog"
"Animal 2 is a cat"
"Animal 3 is a fish"
"Animal 4 is a squirrel"
"loop is finished!"

However, with some delays on accessing the array from the server, I am getting:

"loop is finished!"
"Animal 1 is a dog"
"Animal 2 is a cat"
"Animal 3 is a fish"
"Animal 4 is a squirrel"

How do I ensure the whole loop is complete before moving onto the next tasks in the code?

I want "loop is finished!" to show no matter what the network activity is, or what delays may be put within the for loop.

Here's the 'original code':

fetch('http://localhost:3000/pet/'+pet)
  .then(res => res.json())
  .then(data => {
    const newData = (data);
    for (var x in newData) {
      finalpetName.push(newData[x].petName);
      console.log('pet' + x + 'is retrieved');
    };
  })
  .catch(err => {
    console.error(err)
  });
console.log('loop is finished!');
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
SGPascoe
  • 33
  • 8
  • I don't see any asynchronous code in your example? If you need to wait for an asynchronous function to complete for progressing your code, you need to use the [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) keyword. – Mark Hanna Nov 16 '21 at 02:46
  • I've been trying all evening using tons of different variants on the promise and await and async and others, but nothing seems to be working. I just wanted a super super basic example using the extremely basic code above. Every other question on here contains way too much additional information from the users original code. I thought I'd ask a nice simple animal array example to learn the process, which I can then use for my own work, instead of pasting my code and asking for a fix. – SGPascoe Nov 16 '21 at 02:48
  • 1
    The code in your question does not and will not produce the problem you describe. For useful responses, show your actual code. – CertainPerformance Nov 16 '21 at 02:50
  • Showing the original code would add too much unnecessary information. Imagine there's a delay getting the array from a server, and you have the original code. – SGPascoe Nov 16 '21 at 02:52
  • Unfortunately someone closed your question, so we won't be able to post an answer. But are you basically trying to do this? (Sorry about the one-liner, comments can't have line breaks I don't think) `for (var x in animals) { asyncFunction(x); }` – Mark Hanna Nov 16 '21 at 02:55
  • SHOW REAL CODE! Your sample code does not show the real problem. – epascarello Nov 16 '21 at 02:58
  • lets say I have function 1, function 2, for loop, function 3, function 4.... right now with the server delay, the for loop is completing after function 4! I'd like to pause the entire code until the for loop is completed, and then continue to run function 3 and 4 afterwards. – SGPascoe Nov 16 '21 at 02:59
  • Jesus guys. My real code is a basic for loop like this, but there is a delay due to the backend. You're welcome to simulate a random delay, but that's not in my actual code. My actual code looks just like this except the array is on a database. Do you want to connect to my localhost and my database too to have the full thing? – SGPascoe Nov 16 '21 at 03:01
  • 1
    It matters. There is nothing asynchronous in the code you shared. The back end having delays means nothing when the code is synchronous. So Yes, the real code makes a difference if it is asynchronous. You say "except the array is on a database" Well where is the database calls??? That is the asynchronous part that is missing that is causing you the problems. – epascarello Nov 16 '21 at 03:19
  • It's just obfuscating the issue. No more code is needed. How do you ensure the for loop runs before anything else? That's all that needs answering. I'm not asking for database help. Why would I give a ton of code that has nothing to do with the problem. It would just be more work, and more confusing for myself, you, and anyone who comes across this question in the future. How are people supposed to learn if more complex problems are preferred. I need very basic help with this one very basic code. – SGPascoe Nov 16 '21 at 03:56
  • It's not our job to imagine what your code actually is, it's your job to provide code that is actually representative of the problem. You have not given us any solid indication as to what your asynchronous code actually is. – Jon P Nov 16 '21 at 04:05
  • 1
    No it is more confusing when you do no provide actual code that can reproduce the problem. Your example code does NOT have any problems. If you would have given code, you would have had an answer over an hour ago from this comment. – epascarello Nov 16 '21 at 04:35
  • There you go, there's a fetch at the end of the question. How do I get the 'loop is finished' log (and everything that comes after) to always play after the for loop? It doesn't change the problem at all. It's still a for loop that needs to complete before the end log. – SGPascoe Nov 16 '21 at 05:50
  • If the question gets re-opened I will answer properly (voted to re-open), now we have meaningful code, we can finally answer the question. You need something to execute after your async block has finished, use `finally()` eg `.catch(/*Your code*/).finally(() => console.log('loop is finished!'); )` . The important info is your async call, not really the loop. – Jon P Nov 16 '21 at 22:56

1 Answers1

1

fetch is asynchronous. Anything after your fetch block is not dependent on what is happening in there to complete.

You have a couple of options.

Option 1: Move console.log('loop is finished!'); to call back in the second then method.

fetch('http://localhost:3000/pet/'+pet)
  .then(res => res.json())
  .then(data => {
    const newData = (data);
    for (var x in newData) {
      finalpetName.push(newData[x].petName);
      console.log('pet' + x + 'is retrieved');
    };
    console.log('loop is finished!');
  })
  .catch(err => {
    console.error(err)
  });

Option 2: Use finally if you want it to execute after all the asynchronous work is done, including handling any errors

fetch('http://localhost:3000/pet/'+pet)
  .then(res => res.json())
  .then(data => {
    const newData = (data);
    for (var x in newData) {
      finalpetName.push(newData[x].petName);
      console.log('pet' + x + 'is retrieved');
    };
  })
  .catch(err => {
    console.error(err)
  })
  .finally(() => console.log('loop is finished!'));
Jon P
  • 19,442
  • 8
  • 49
  • 72