javascript: ¿Cómo se puede configurar una variable, inicializada fuera de una promesa, desde dentro de la promesa?

CorePress2024-01-24  9

Esta pregunta ya tiene respuestas aquí: ¿Por qué mi variable no se modifica después de modificarla dentro de una función? - Referencia de código asincrónico

(7 respuestas)

Cerrado

hace 2 años

.

Bien, tengo una variable válida que se define antes de una promesa como verdadera. Luego tengo la promesa misma donde quiero actualizar esa variable válida en el.then(() => {}) constructor dependiendo de la información que reciba de la promesa. Sin embargo, parece haber un problema de sincronización ya que ocurre de forma asincrónica. ¿Alguna idea de cómo puedo tomar el valor de la promesa y actualizar la variable para poder acceder a esa información fuera de la promesa?

Aquí está el código completo:

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
  }


------------------------------------

Lo que intentas hacer es algo que todo programador de JavaScript (incluido yo mismo) intenta y fracasa en algún momento de su carrera. Simplemente no puedes hacer que funcione como esperas.

Puedes configurar una variable global desde dentro de una promesa u otra devolución de llamada asincrónica,y parece que tu código debería hacer eso.

Sin embargo, esto no resuelve el otro problema que mencionaste: estas devoluciones de llamada se ejecutan de forma asincrónica.

En algún lugar, tienes un código que quiere ver tu variable válida y realizar alguna acción basada en ella. Pero, ¿cómo sabe este código cuándo se completó la devolución de llamada de su promesa, por lo que válido es válido (juego de palabras)? No lo hará.

Lo que debes hacer es poner ese código en una función, llamarlo desde tu devolución de llamada y pasar el indicador válido como argumento. De esa manera, la función se ejecutará en el momento adecuado, después de que la devolución de llamada haya determinado si hay usuarios no válidos.

Y ahora no necesita la devolución de llamada global ni la segunda promesa. Podría verse así:

"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
}

También agregué un comando "uso estricto"; en elparte superior de su código para ponerlo en modo estricto y le recomendamos que siempre lo haga también. El for (usuario en datos) crea inadvertidamente una variable global usuario porque no hay const, let o var allí. El modo estricto evitaría este error.



------------------------------------

Es posible que necesites 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.

})()

O puedes embellecer el código como este:

(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;
        }
    }
}

})

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare