Home > Back-end >  How can I get this NodeJS asynchronous loop to execute properly?
How can I get this NodeJS asynchronous loop to execute properly?

Time:06-23

I have tried a thousand ways to do this, but none work properly. Here msg1 and msg2 are stand ins for functions that I want to call synchronously (first one then the other). A for loop produces "unknown" in the second loop. After searching, I think this is the right way to do it, but I am still not there. The answer that I would like to get is:

msg1
msg2

but I am getting

msg1
msg1

Here is my code

var data = {
  "messages": ["msg1", "msg2"],
  "i": -1
}

const increment = async () => {
  data.i = await data.i   1;
};

const test = async () => {
  data.messages.forEach((fcn) => {
    increment(data)
    .then(() => {
      console.log(data.messages[data.i])
      return data
    })
  })
};

test(data)

UPDATE

the asynchronous answer from jfriend00 (below) works!!! BUT, when used in my actual code, it runs one extra time producing "undefined" in the final loop. I have tried changing the starting value for i, different formulations of the for loop and adding a check for the value "undefined" (as below), but the undefined value remains goes undetected. I have also lengthened the delay (unsuccessful). How can I ensure that the loop only runs once per message?

if (data.i !== undefined) {
 console.log(data.messages[data.i])     
}

CodePudding user response:

Since there's nothing asynchronous here, you can just remove all the async, await and .then() and then run your synchronous code (you can run each of these snippets directly, right in the browser to see what they send to the console).

var data = {
    "messages": ["msg1", "msg2"],
    "i": -1
}

const increment = () => {
      data.i;
};

const test = () => {
    data.messages.forEach((fcn) => {
        increment(data)
        console.log(data.messages[data.i])
    });
};

test(data)


If you want the increment() function to be an actual asynchronous operation and you want to sequence the calls to increment() then, you have to ditch .forEach() and use a for loop and use await appropriately and insert something that is actually asynchronous into the increment() function (I inserted a promise-based delay):

function delay(t) {
    return new Promise(resolve => {
        setTimeout(resolve, t);
    });
}

var data = {
    "messages": ["msg1", "msg2"],
    "i": -1
}

const increment = async () => {
    await delay(100);
      data.i;
};

const test = async () => {
    for (let msg of data.messages) {
        await increment(data);
        console.log(data.messages[data.i])
    }
};

test(data)

Comments

Your existing code is misusing async, await and .then(). There are no asynchronous operations anywhere in your existing code so there's no reason for any of async, await and .then() as that just makes things more complicated than required.

In addition, you only ever use await when you are awaiting a promise. So, data.i = await data.i 1; is misguided. It will run, but the await doesn't do anything useful - it only makes the code more complicated.

  • Related