2

Ok, so I have a variable valid that is defined before a promise as true. Then I have the promise itself where I want to update that valid variable in the .then(() => {}) constructor depending on what information I receive from the promise. However, there seems to be a timing issue since it occurs asynchronously. Any idea how I can take the value from the promise, and update the variable so that I can access that information outside the promise?

Here's the full code:

var valid = true;
firebase.database().ref(path).once('value')
  .then((snap) => {
    const data = snap.val()


    if (data !== null) {
      for (user in data) {
        if (data[user].Email === Email) {
          valid = false;
        }

      }
    }
  })
  .then(() => {
    return valid
  }
Max Gertner
  • 59
  • 1
  • 4

2 Answers2

3

What you're trying to do is something every JavaScript programmer (myself included) attempts and fails at somewhere in their career. You simply can't make it work the way you are hoping.

You can set a global variable from inside a promise or other asynchonous callback, and it looks like your code should do that.

However, this does not solve the other problem you mentioned: these callbacks are run asynchronously.

Somewhere, you have some code that wants to look at your valid variable and take some action based on it. But how does this code know when your promise callback has completed, so valid is valid (pun intended)? It won't.

What you need to do is put that code in a function, call it from your callback, and pass the valid flag as an argument. That way the function will be run at the right time, after the callback has determined whether there are any invalid users.

And now you don't need the global or the second promise callback. It might look something like this:

"use strict";

firebase.database().ref(path).once('value')
  .then((snap) => {
    const data = snap.val();
    if (data) {  // You shouldn't need the '!== null'
      for (const user in data) {  // There was a 'const' missing here
        if (data[user].Email === Email) {
          allUsersAreValid(false);
          return;
        }
      }
    }
    allUsersAreValid(true);
  });

function allUsersAreValid( valid ) {
  // Do something here
}

Also I added a "use strict"; at the top of your code to put it in strict mode, and recommend you always do that too. The for (user in data) inadvertently creates a global variable user because there is no const or let or var there. Strict mode would prevent this error.

Michael Geary
  • 28,450
  • 9
  • 65
  • 75
-1

You may need await/async.

(async(){

var valid = true;
await new Promise(rs=>{
firebase.database().ref(path).once('value')
  .then((snap) => {
    const data = snap.val()

    if (data !== null) {
      for (user in data) {
        if (data[user].Email === Email) {
            valid = false;
            break;
        }
      }
    }
    rs();
  })
})

// 'valid' is false here if condition is true.

})()

Or you can beautify code like this:

(async(){

var valid = true;
var snap = await firebase.database().ref(path).once('value');
const data = snap.val();
if (data !== null) {
    for (user in data) {
        if (data[user].Email === Email) {
            valid = false;
            break;
        }
    }
}

})
Evan Hsu
  • 82
  • 6