¿Por qué onSnapshot() se ejecutó en último lugar?
Quiero crear una función de Registro en Javascript que cargue la información de registro en Firebase Firestore y la registre en la consola cuando finalice la carga.
- Quiero que el flujo de trabajo de mi consola sea así: registrar datos de Firestore a la consola -> establecer elemento en localStorage -> alerta -> redirigir a otra página
- Pero de alguna manera el flujo es el siguiente: configure el elemento en localStorage -> alerta -> redirigir a otra página (y nunca registre datos de Firestore en la consola)
- Cuando omito la redirección, el flujo es: configurar el elemento en localStorage -> alerta -> registrar datos de Firestore a la consola
También quiero incluir la identificación de usuario en los datos cargados en Firestore. ¿Cómo puedo obtenerlo?
Explíqueme por qué sucedió esto y qué puedo hacer para lograr el resultado deseado. Gracias por tu
Fragmento de código
import { createUserWithEmailAndPassword } from 'https://www.gstatic.com/firebasejs/10.7.2/firebase-auth.js';
import { collection, onSnapshot, addDoc } from "https://www.gstatic.com/firebasejs/10.7.2/firebase-firestore.js";
import { auth, isArtist, firestore } from "./firebase-config.js";
// if isArtist: profile(publish, no playlist)
// if !isArtist: profile(no publish, playlist)
isArtist();
const Register = async (auth, email, password) => {
let isChecked;
let info;
try {
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
isChecked = true;
} catch (error) {
isChecked = false;
info = error.code;
}
return {
info,
isChecked,
};
};
const RegisterPage = () => {
document.getElementById("btn-register").onclick = async () => {
let email = document.getElementById('email-register').value;
let password = document.getElementById('password-register').value;
let username = document.getElementById('username-register').value;
let isArtist = localStorage.getItem("isArtist");
// let user = userCredential.user;
const isSuccess = await Register(auth, email, password);
// Inheritance of OOP: isChecked is a local variable of Register
// After assigning Register to isSuccess -> isSuccess can use isChecked
if (isSuccess.isChecked) {
// Compile acc info
const data = {
dateRegistration: Date.now(),
// userID: user.uid,
email,
username,
isArtist,
};
// Upload acc info to Firestore
const colRef = collection(firestore, "accounts");
addDoc(colRef, data)
.then(() => {
// Kiểm tra Firestore
onSnapshot(colRef, (snapshot) => {
const output = [];
snapshot.docs.forEach((doc) => {
output.push({...doc.data()});
});
console.log(output);
});
localStorage.setItem("email", email);
alert("Register successful");
window.location.href = "home.html";
})
.catch((error) => {
alert("Error uploading data to Firestore:", error);
})
} else {
alert("Register fail");
}
};
};
RegisterPage();
Esto se debe a que JavaScript no espera que se onSnapshot()
complete la ejecución de la devolución de llamada pasada antes de pasar a la siguiente línea.
Dado que, en su caso, desea obtener los documentos de las colecciones solo una vez, debe utilizar el getDocs()
método asincrónico de la siguiente manera. Observe cómo gestionamos la asincronicidad de las diferentes llamadas a los métodos de Firebase usando await
:
// ...
if (isSuccess.isChecked) {
// Compile acc info
const data = { ...};
// Upload acc info to Firestore
const colRef = collection(firestore, "accounts");
await addDoc(colRef, data); // Your function is async, so use await!
const snapshot = await getDocs(colRef); // See the await keyword
const output = [];
snapshot.docs.forEach((doc) => {
output.push({ ...doc.data() });
});
console.log(output);
localStorage.setItem("email", email);
alert("Register successful");
window.location.href = "home.html";
} else {
alert("Register fail");
}