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.