0

I need to re-execute a hand made for loop (because I need time between each step) 10s after it ends forever.

So after few tries, I came with this code, but it doesn't work because it re-executes every 10s, not after the loop finishes. I tried to but async function in the interval and put all my code in an await one, but it didn't work.

async function refreshEDT() {
    let rows = appModel.getAll()
    let orderFiliere = {};
    await rows.then((res) => {
        for (let i = 0; i < res.length; i++) {
            if (res[i].filiere in orderFiliere) {
                orderFiliere[res[i].filiere].push(res[i])
            } else {
                orderFiliere[res[i].filiere] = [res[i]]
            }
        }
    })
    return orderFiliere
}

let edt = refreshEDT()
setInterval(() => {
    edt = refreshEDT()
}, 1000 * 60 * 60) //ms to s to m to h
setInterval(() => {
    edt.then((lessons) => {
        (function loop(i) {
            let lessons_key = Object.keys(lessons)
            setTimeout(() => {
                // processing things
                if (--i) loop(i);
            }, 1000 * 10) //ms to s to 10s
        })(Object.keys(lessons).length - 1)
    })
    console.log(1)
}, 1000 * 10) //ms to s to 10s

Do you have any solution?

Ty!

EDIT Let's explain what I try to do: I get things on my DB, try to classify by "filiere", one of my column, and return that object. Those data are reloaded every hour. After that, I need to emit with socket.io every "filiere" with 10s between, and repeat that.

Nathan
  • 21
  • 6
  • It doesn't make sense to do `edt.then()` more than once. After the first time it will resolve immediately with the same value as before, unless `edt` isn't really a promise and it's just a promise-like object. – Patrick Roberts Mar 21 '22 at 17:31
  • 2
    I'm not totally clear on the specification here. The inner loop runs with what delay, exactly? What are you trying to accomplish here? Looks like there's a promise in there too... more details seem needed. – ggorlen Mar 21 '22 at 17:31
  • I interpreted the request to mean @Nathan wanted to re-run the code in the body of `setInterval` 10 seconds after the inner loop completes, but that interpretation could very well be wrong based on the confusion I expressed in my previous comment. – Patrick Roberts Mar 21 '22 at 17:33
  • Isn't this exactly what `setInterval()` is designed to do? – Ryan O'D Mar 21 '22 at 17:33
  • I edited with more code. setInterval() & setTimeout don't block, so it just re-executes every 10s. Yes, that's what I meant @PatrickRoberts ! – Nathan Mar 21 '22 at 17:36
  • I'm also somewhat unclear on what is intended to happen. I understand "I need time between each step". And I also think I that you want to re-execute the loop 10 seconds after the last iteration of the loop executes. It is a bit confusing to me that you coincidentally have the same time between iterations and between restarts, in which case, maybe just have one endless loop where the counter wraps around. Or conditionally select a longer (or shorter) delay on the last iteration. – Wyck Mar 21 '22 at 17:38
  • 1
    you got more code than explanation here, which is confusing... can you try to elaborate more? – MartianMartian Mar 21 '22 at 17:40
  • @Wyck I need to emit with socket every 10s, so I was thinking to browse all my promise and re-execute – Nathan Mar 21 '22 at 17:41
  • In JavaScript that is written as: `setInterval(emitWithSocket, 10000)` – Wyck Mar 21 '22 at 17:42
  • try to use only one setInterval, coz they will cause racing. you can look into Promise.all() – MartianMartian Mar 21 '22 at 17:43
  • I tried to explain what I'm trying to do, but I'm nor experimented with JS nor native English speaker, so sorry if my explanation isn't clear – Nathan Mar 21 '22 at 17:45
  • You might be a fan of writing a [`sleep`](https://stackoverflow.com/a/39914235/1563833) function and using `await sleep(1000* 10)` in a traditional loop in your async function. – Wyck Mar 21 '22 at 17:52
  • await doesn't stop for loops, but I got answered ! – Nathan Mar 21 '22 at 17:55

3 Answers3

1

Perhaps the code will be easier to read when you wrap setTimeout with a promise to await.

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

async function refreshEDT() {
  const res = await appModel.getAll();
  const orderFiliere = res.reduce((acc, value) => {
    const { filiere } = value;

    if (filiere in acc) {
      acc[filiere].push(value);
    } else {
      acc[filiere] = [value];
    }

    return acc;
  }, {});

  return orderFiliere;
}

// consider naming this
(async () => {
  let edt = refreshEDT();

  setInterval(() => {
    edt = refreshEDT();
  }, 1000 * 60 * 60);

  while (true) {
    const lessons = await edt;

    for (const lessons_key of Object.keys(lessons)) {
      await sleep(1000 * 10);
      // processing things
    }

    // repeat after 10 seconds
    await sleep(1000 * 10);
  }
})();

With ES2022, you can use Array.prototype.groupBy() to simplify your refreshEDT() implementation:

async function refreshEDT() {
  const res = await appModel.getAll();
  const orderFiliere = res.groupBy(({ filiere }) => filiere);

  return orderFiliere;
}
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
0

You could try using setTimeout to call your function again.

const myFunc = () => {
    
    // processing things

    setTimeout(myFunc , 10000)
}
myFunc();
Gustavo Cesário
  • 1,310
  • 1
  • 12
  • 23
0

I think this could help if i understood the problem correctly :

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async yourFunction() {
  const secondsToWait: number = 10;
  let i = 0;
  for (let item of List) {
    // Do stuff
    
    if (i === list.length -1) {
      await wait(secondsToWait*1000);
      yourFunction();
    }
    i++;
  }
}