Quiero configurar un contador en mi base de datos en tiempo real de firebase. En mi aplicación, trato de usarla para contar el número de solicitudes de API. A continuación se muestra la extracción más corta y simple del código de mi aplicación que funciona exactamente igual y produce el mismo error que en mi aplicación.
Estructura de mi base de datos en tiempo real de firebase:
Counter: 1000
Mi código (indd.js):
require('dotenv').config(); const admin = require("firebase-admin"); admin.initializeApp({ credential: admin.credential.applicationDefault(), databaseURL: "https://awesomeURL.firebaseio.com" }); const database = admin.database(); const rw = () => { const path = "Counter"; database.ref(path).on("value", snapshot => { database.ref(path).set(snapshot.val() - 1); console.log(snapshot.val()) }); } rw();Contenido de mi archivo package.json
"name": "api", "version": "1.0.0", "description": "All my APIs.", "main": "indd.js", "dependencies": { "dotenv": "^10.0.0", "firebase-admin": "^8.6.1" }, "scripts": { "start": "nodemon indd.js" }, "engines": { "node": ">=12" } }El contenido de mi archivo .env .
El archivo json requerido está disponible en Descripción general del proyecto ⚙️ > Cuentas de servicio > Generar nueva clave privada
GOOGLE_APPLICATION_CREDENTIALS = ./adminsdk.json
resultado :
Los datos se reducen con éxito en la base de datos en tiempo real de Firebase y la aplicación falla y produce el siguiente error. Enlace de Pastebin del mensaje de error en la consola
database.ref(path).on("value", snapshot => { database.ref(path).set(snapshot.val() - 1); console.log(snapshot.val()) }); Entonces, aquí on método de disparo tan pronto como actualice el valor, que nuevamente actualiza el valor, así que esto está creando un bucle
update value -> on method fired -> update value -> on method fired ->..... infinite.
En lugar de usar on método, lea el valor una vez usando get o un método similar y luego actualice su valor
Nota: - Una mejor manera sería usar la transacción
Está adjuntando un oyente permanente al Counter llamando on . Entonces, su código será llamado una vez con el valor inicial del contador, y luego cada vez que se cambie el contador.
Y dado que su código de devolución de llamada cambió el contador, eso hará que la devolución de llamada se vuelva a llamar... y otra vez... y otra vez, hasta que obtenga el error que recibió.
Para incrementar el valor, solo debe obtener el valor actual y no escuchar las actualizaciones, lo que puede hacer usando once() en lugar de on() :
const rw = () => { const path = "Counter"; // 👇 database.ref(path).once("value", snapshot => { database.ref(path).set(snapshot.val() - 1); console.log(snapshot.val()) }); } rw();Pero incrementar el valor existente hoy en día se puede hacer aún más fácil (y más seguro) usando la operación de incremento del lado del servidor atómico :
const rw = () => { const path = "Counter"; // 👇 👇 database.ref(path).set(firebase.database.ServerValue.increment(1)); } rw();