Run asynchronous JavaScript functions inside a forEach loop synchronously [duplicate] - javascript

This question already has answers here:
Resolve promises one after another (i.e. in sequence)?
(36 answers)
Closed 2 years ago.
I'm developing an app and I'm having a problem. I want to run two functions inside a forEach loop, which means for each iteration run both functions once.
This is very simple to do when you think about it, but my functions are asynchronous and my first function needs to finish before the second one executes.
Reason why i made these functions async is that in my app these functions represent an API call.
I will show you a quick example in which i used setTimeout() instead of API calls.
async function f(){
await setTimeout(()=>{
console.log("FIRST")
},1000)
}
async function f2(){
await setTimeout(()=>{
console.log("SECOND")
},3000)
}
for(var i = 0;i < 5; i++){
f()
f2()
}
When I run this the output is:
FIRST
FIRST
FIRST
FIRST
FIRST
SECOND
SECOND
SECOND
SECOND
SECOND
And i need my output to be:
FIRST
SECOND
FIRST
SECOND
FIRST
SECOND
FIRST
SECOND
FIRST
SECOND
Any idea how to achieve this? Would be very helpful.

Wait for the first async function to finish and then call the second one
for(var i = 0;i < 5; i++){
f1().then(res => {
return f2()
}
}
This will not guarantee your desired output, but will guarantee that a call to f2 was done after a call to f1
Note: you could collect all promises into an array and maybe call Promise.all if you want to know when all of them are finished.

Related

Run a function against each object in an array in parallel? [duplicate]

This question already has answers here:
Wait until all promises complete even if some rejected
(20 answers)
Closed 2 months ago.
I have an array
var array = ["First","Second","Third"]
let i = 0;
I want it to run each object in the array across the same async functions at the same time
for (;i < arbAgainstLength;) {
const first = async () => {
//do some await stuff
}
const second = async (param1, param2) => {
//do other await stuff
}
}
This bot is monitoring price changes, so I'm looking for it to only take action on a specific object at the time that object meets the proper criteria.
So, if First meets the criteria, it will complete the rest of the sequence, but Second and Third will continue to listen.
Then, finally, once the sequence is complete for an object, I'd like to put that object BACK into the async functions.
Currently, and this is probably expected, the function only runs fully if it's the last object in the array
Is it possibly a forEach instead of a for? Or is a promise needed as well?
I have tried async.parallel and promises. If the answer is a promise, I think I may be still trying to grasp how they work exactly.
I think there was a lack of proper verbage in my question but I ended up finding that it was best used as a promise.all with a forEach inside it.
Thanks for all that!

How is setTimeout called in a for loop js? [duplicate]

This question already has answers here:
What is the JavaScript version of sleep()?
(91 answers)
Closed 2 years ago.
I am trying to write a for loop that has a delay between running each iteration. I thought Id go about it by using setTimeout() as follows.
Input:
for (let i=0;i<3;i++){
setTimeout(()=>{console.log("hi")},10000)
}
Output:
hi
hi
hi
What seems to be happening is that its waiting 10 seconds and then runs the entire for loop, rather than waiting 10 seconds to run each iteration of the for loop. After the first hi is shown to the console, the other 2 follow instantaneously. Why is this the case, rather than a delayed logging of hi and how can I go about doing this?
You don't call setTimeout() inside a for loop. You replace the for loop with setTimeout():
let loop = 0;
function loop () {
console.log("hi");
x++;
if (x<3) {
setTimeout(loop, 10000);
}
}
loop();
This is the traditional way of doing it. You can use a Promise with async/await in modern js to use the for loop again:
// First we need a promisified setTimeout:
function delay (ms) {
return new Promise((resolve,reject) => setTimeout(resolve,ms));
}
async function test () {
for (let i=0;i<3;i++){
await delay(10000);
console.log("hi");
}
}
test();
Javascript is asynchronous which means your timers start immediately rather than each timer blocking until done, and they all execute after roughly 10s plus a few ticks.
If you want you can try setInterval with a counter to clear it:
var counter = 0;
var interval = setInterval(function(){
console.log("hi");
counter+=1;
if (counter == 3) { clearInterval(interval); }
}, 10000);
You can probably work out an alternative using setTimeout as well.

calling multiple setInterval() functions in js with a loop [duplicate]

This question already has answers here:
setTimeout in for-loop does not print consecutive values [duplicate]
(10 answers)
Closed 5 years ago.
I'm new to javascript and I'm having trouble using the setInterval() function properly.
Basically I want to call a function at different given intervals for different parameters both of which I have in lists.
I have a function called myfunction. I have a list called myparam with all of the variables I want to pass this function. And finally I have a list called myfrequency which is the time in millis that I want between each call of myfunction with the parameter given in myparam. I'm trying something like this but it's not working:
for(i=0;i<myparam.length();i++;){
setInterval(function(){myfunction(myparam[i]);},myfrequency[i]);
}
The result of the above code is that it works only for the last index. myfunction gets called at the correct interval with the correct parameter for ONLY the last value in myparam.
Why does this happen? Is my thinking that setInterval() sets up the calling of a function at an interval incorrect?
Well it's because setInterval has a delay which means when the interval runs
the loop is already been finish
To do that just create another function which will start your interval
function StartInterval(index, frequency) {
setInterval(function(){
myfunction(index);
},frequency);
}
Then inside your loop just call this function and pass something
for(i=0;i<myparam.length;i++){
StartInterval(myparam[i], myfrequency[i])
}
/** set what value you want **/
var myparam = [10,20,30];
var myfrequency = [1000,2000,3000];
function myfunction(index) {
console.log(index);
}
function StartInterval(index, frequency) {
setInterval(function(){
myfunction(index);
},frequency);
}
for(i=0;i<myparam.length;i++){
StartInterval(myparam[i], myfrequency[i])
}

Will my map function always run first [duplicate]

This question already has answers here:
Are all javascript callbacks asynchronous? If not, how do I know which are?
(5 answers)
Closed 6 years ago.
Will the map function always finish running before the if statement runs? I want to make sure that the elements in the array are always added up before the if statement runs. Will there ever be a time when the map function doesn't finish running before the if statement starts and so the if statement will not get the true value of the add variable?
var arr = [ '33.3%', '33.3%', '33.3%' ];
var add = 0;
arr.map(function(elem){
add += parseInt(parseFloat(elem)*10000)
});
if (add <= 1001000 && add >= 999000) {
console.log("passed!!")
}
Yes. Unless you have asynchronous requests or multi-threaded operations like WebWorkers, your code is synchronous, i.e. it is executed in strict order.
Array.prototype.map of javascript is synchronous, but if you want an async behaviour you can use nodejs async module.
NodeJS Async Map
var async = require('async');
var arr = ['1','2'];
async.map(arr, getInfo, function (e, r) {
console.log(r);
});
function getInfo(name, callback) {
setTimeout(function() {
callback(null, name + 'new');
}, 1000);
}
http://code.runnable.com/UyR-6c2DZZ4SmfSh/async-map-example-for-node-js

How to setTimeout inside a loop [duplicate]

This question already has answers here:
Why is my function call that should be scheduled by setTimeout executed immediately? [duplicate]
(3 answers)
Closed 6 years ago.
Are you trying to set a timeout to run multiple functions with some delay between them? Is the timeout inside of a for loop? Are your functions all firing off at the same time, and not respecting the timeout, or otherwise causing messy behaviour?
It is intuitive, but incorrect to write it like this:
for (var i = 0; i < moves.length; i++) {
setTimeout(chooseOne(moves[i]), i * 1000 + 1000);
}
SOLUTION:
The solution is to pass the i values to the timeout indirectly, like this. Write the loop, call your timeout function inside the loop and pass that function the i value.
function clickedOne() {
for (var i = 0; i < moves.length; ++i) {
myTimeout(i);
}
}
then in a separate function, set the timeout, pass an anonymous function as your first parameter, inside that function I call my chooseOne function and pass it the unique value for each iteration. Now you can write a comma, and provide the second parameter for setTimeout which is your timeout. My timeout is one second times i, so each function will execute one second after the one that precedes it.
function myTimeout(i) {
setTimeout(function() { chooseOne(moves[i]); }, 1000 * i);
}
I actually don't know why this works and the first method does not.
Try this:
var i = 0;
setTimeout(function(){
if(i < moves.length){
chooseOne(moves[i++]);
}
}, i * 1000 + 1000);

Categories

Resources