4

An example of simple nested for loop:

for (let i=0; i<=2; i++) {
  for (let j=0; j<=1; j++){
    console.log("i is: " + i);
    console.log("j is: " + j);
    console.log("---");
  }
}

Nested for loop with delay:

for (let i=0; i<=2; i++) {
  for (let j=0; j<=1; j++){
    task(i,j);
  }
} 

function task(i,j) { 
  setTimeout(function() { 
    console.log("i is: " + i);
    console.log("j is: " + j);
    console.log("---")
  }, 1000 * i);
}

NOW MY QUESTION IS

How can I delay each loop seperately.

Current output (ignore the "---"):

i, j, delay, i, j, delay, ...

Desired output (ignore the "---"):

i, delay, j, delay, i, delay, j, delay ...

I tried things like below (but its returning a complete wrong output)

for (let i=0; i<=2; i++) {
  for (let j=0; j<=1; j++){
    taski(i);
    taskj(j)
  }
} 

function taski(i) { 
  setTimeout(function() { 
    console.log("i is: " + i);
  }, 1000 * i);
}
function taskj(j){
  setTimeout(function() { 
    console.log("j is: " + j);
    }, 1000 * j);
}
Evik Ghazarian
  • 1,803
  • 1
  • 9
  • 24
  • You'd want `setTimeout(…, 1000*(i*3+j))`. However I would recommend to simply use [`await delay(1000)` with promises in an `async function`](https://stackoverflow.com/a/44476626/1048572) which works without any complicated calculations. – Bergi Aug 21 '20 at 18:49

3 Answers3

3

You could use Promise and async/await to handle sequential call

function taski(i) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      console.log("i is: " + i)
      resolve()
    }, 1000 * i)
  })
}
function taskj(j) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      console.log("j is: " + j)
      resolve()
    }, 1000 * j)
  })
}

async function execute() {
  for (let i = 0; i <= 2; i++) {
    for (let j = 0; j <= 1; j++) {
      await taski(i)
      console.log("delay")
      await taskj(j)
      console.log("delay")
    }
  }
}

execute()

Reference:

hgb123
  • 13,869
  • 3
  • 20
  • 38
3

Ok the thing is setTimeout works in it's own world that isn't limited by the for loops, or any other code for that matter, it doesn't actually "block" the current code at all, in the for loop you are just setting up a bunch of intervals, really fast one after the other (since the for loop doesn't stop or get delayed by the timeouts), which later execute in some unknown order when the time for each one individually runs out, which is not blocked or dependant on any of the other timeouts

If you want to keep relatively the same format you have now, but with delay blocking you can use await and promises and async functions

(async () => 
for (let i=0; i<=2; i++) {
  for (let j=0; j<=1; j++){
    await taski(i);
    await taskj(j)
  }
} 
)()
function taski(i) { 
  return new Promise((rs) => setTimeout(function() { 
    res(console.log("i is: " + i));
  }, 1000 * i));
}
function taskj(j){
    return new Promise((rs) => setTimeout(function() { 
    res(console.log("j is: " + j)
    }, 1000 * j));
}


2

You could try to to an asynchronous approach with async/await:

function sleep(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}

(async function() {
  for (let i = 0; i <= 2; i++) {
    for (let j = 0; j <= 1; j++) {
      await taski(i);
      await taskj(j);
    }
  }
}())

async function taski(i) {
  await sleep(1000 * i);
  console.log("i is: " + i);
}
async function taskj(j) {
  await sleep(1000 * j);
  console.log("j is: " + j);
}
PotatoParser
  • 1,008
  • 7
  • 19