3

In a for of loop, I want to get a value defined (not empty) before I continue to the next iteration.

Currently, I do a setTimeout() and "hope" that the value is available after 3 seconds. Poor practice.

Is there a way to pause the loop iteration until the value is available, and then continue the loop?

// get a tags in array
const $j_object = $(".name");
        
for (const element of $j_object) {

    // timeout
    await new Promise(resolve => setTimeout(resolve, 3000));

    // get value
    value_name = await GM.getValue("value_name");

    // wait until value_name is defined until we continue...!
}
Henrik Petterson
  • 6,862
  • 20
  • 71
  • 155
  • 2
    @RoryMcCrossan Can you please post an answer demonstrating this with my code as reference? Thanks. – Henrik Petterson May 26 '21 at 10:08
  • 4
    @RoryMcCrossan Why couldn't you? `await` works perfectly in a `for` loop – Jeremy Thille May 26 '21 at 10:09
  • 2
    Does this answer your question? [While variable is not defined - wait](https://stackoverflow.com/questions/7307983/while-variable-is-not-defined-wait) – 0stone0 May 26 '21 at 10:10
  • Maybe something along the lines of `while ((value_name = await GM.getValue('value_name')) === undefined) await new Promise(resolve => setTimeout(resolve, 500))` – CherryDT May 26 '21 at 10:10
  • I think `await` is good ideal? why you don't try that? – Duc Nguyen May 26 '21 at 10:15
  • @JeremyThille that's a good point. I didn't test `await`, however the OP is already using it – Rory McCrossan May 26 '21 at 10:15
  • @RoryMcCrossan but not to keep checking for the value - they are using it to load the value only once. – CherryDT May 26 '21 at 10:16
  • 1
    @CherryDT Your solution actually works. Please post as an answer explaining it so that i can accept it. – Henrik Petterson May 26 '21 at 10:18
  • 2
    It may work, but note that the `while` loop with freeze the browser. What work does `GM.getValue()` do? Can you not amend it to work with promises more effectively, by resolving when it *actually has a value*? – Rory McCrossan May 26 '21 at 10:19
  • 1
    @RoryMcCrossan : No it won't freeze the browser, there is an `await` in the `while`. – CherryDT May 26 '21 at 10:23
  • Why is `GM.getValue` returning a value that isn't defined yet? – Alnitak May 26 '21 at 10:26
  • 1
    Ugh, I keep missing the damn `await`. My bad. However I'd argue the pattern should be changed so that whatever logic is called in `GM.getValue()` works with the promises more effectively, as I stated in the previous comment. – Rory McCrossan May 26 '21 at 10:26
  • @RoryMcCrossan agreed - this design seems fundamentally flawed/ – Alnitak May 26 '21 at 10:27
  • 1
    @RoryMcCrossan: [GM.getValue](https://wiki.greasespot.net/GM.getValue) reads a value from Greasemonkey/Tampermonkey's local storage, I'm assuming it will be set by some separate piece of code at some point. There may not be a way to have those pieces communicate. But if there were, then of course using an event emitter would be preferred. – CherryDT May 26 '21 at 10:27
  • Understood. The `GM` naming convention now makes sense. Tagging that in the question may have been helpful. – Rory McCrossan May 26 '21 at 10:30

1 Answers1

2

You could add a loop in which you keep reading the value, with some delay between the reading attempts, breaking the loop when you read something other than undefined.

while ((value_name = await GM.getValue('value_name')) === undefined) {
  await new Promise(resolve => setTimeout(resolve, 500))
}

A less dense way of writing that would be:

while (true) {
  value_name = await GM.getValue('value_name')
  if (value_name !== undefined) break
  await new Promise(resolve => setTimeout(resolve, 500))
}
CherryDT
  • 25,571
  • 5
  • 49
  • 74