Por: Juan Andrés Núñez
Juan Andrés Núñez - juanwmedia

Especialista en tecnologías Web. Me dedico a enseñar desarrollo Web moderno a cualquier persona (físicamente en clase y a través de Internet) desde una perspectiva holística: teniendo en cuenta las competencias técnicas necesarias, junto a las habilidades personales o soft skills. Tienes más información en mi Web.

  • En la lección anterior consultamos documentos y colecciones una vez, es decir, sin escuchar posibles cambios más adelante.
  • Sin embargo Cloud Firestore es una base de datos en tiempo real, por lo que es necesario que entiendas cómo reaccionar ante los cambios del contenido de tu fuente de datos. Es muy sencillo.
  • Si sustituimos get() por onSnapshot() a la hora de consultar un documento o colección, podemos utilizar un callback con su contenido además de seguir recibiendo información cuando este se actualice.
db.collection("users")
      .doc("juanwmedia")
      .onSnapshot(document => console.log(document.data()));
  • Quizás la perspectiva de estar escuchando constantemente el stream de datos desde Firebase te ponga nervioso/a. No sólo a nivel de consumo de datos sino a nivel económico. Sin entrar en mucho detalle (el tema precios lo veremos al final del curso) debes de saber que Cloud Firestore es lo suficientemente inteligente como para utilizar el caché en los documentos que no han cambiado y sólo leer los documentos que sí contienen alguna modificación. Es lo que se llama compensación de latencia.
  • Lo mismo ocurre cuando escribes en Cloud Firestore: verás que el front-end se actualiza instantáneamente aunque probablemente los datos todavía estén viajando hacia el backend. Luego, unos milisegundos después llega la confirmación a través de los metadatos de cada documento.
  • Como ves, aunque no es lo más común ya que Cloud Firestore se encarga de todas esta gestión, si lo quieres puedes escuchar los cambios en los metadatos con la propiedad includeMetadataChanges en valor true.
  • Aunque veremos las consultas en Cloud Firestore muy pronto, podemos utilizar el ahora conocido onSnapShot() para recibir el stream de datos actualizado. Por ejemplo vamos a preguntar cuantos usuarios de nuestra colección users tienen Guizmo como valor de la propiedad name.
db.collection("users")
      .where("name", "==", "Guizmo")
      .onSnapshot(querySnapshot =>
        querySnapshot.forEach(document => console.log(document.id))
      );
  • Como ves, igual que en la lección anterior estamos iterando sobre la propiedad docs del snapshot querySnapshot que nos devuelve la consulta. Si ahora añadimos o eliminamos algún documento que coincida con la consulta, seremos notificados.
  • Sin embargo, como puedes comprobar, cuando hay un cambio en un documento perteneciente a una consulta, se siguen retornando todos los documentos. Si queremos actuar ante una operación de agregar, modificar o eliminar, podemos usar el método docChanges() del querySnapshot retornado en cualquier consulta, y de ahí discriminar con una estructura de control.
db.collection("users")
  .where("name", "==", "Guizmo")
  .onSnapshot(querySnapshot =>
    querySnapshot.docChanges().forEach(change => {
      if (change.typ*e === "added") {
        console.log("Added :", change.doc.data());
      }

      if (change.type === "modified") {
        console.log("Modified :", change.doc.data());
      }

      if (change.type === "removed") {
        console.log("Removed :", change.doc.data());
      }
    })
  );
  • Te habrás dado cuenta de que en la primera carga todos los documentos entran como added. Es normal. De esta forma Cloud Firestore te permite cargar el estado inicial desde la propia consulta, evitando tener que escribir esa lógica en otra parte.
  • Ahora si añadimos propiedades a los documentos o los eliminamos, podemos reaccionar.
  • Por último (pero no menos importante) vamos a ver cómo desconectar estos listeners ya que de lo contrario podrían causar problemas de memoria. Es tan sencillo como envolver la consulta en una variable y luego, cuando ya no queramos seguir escuchando, invocarla.
const unsub = db
      .collection("users")
      .where("name", "==", "Guizmo")
      ...

...
unsub()

No te pierdas ninguna novedad

Escuela Vue en Twitter

Participa en la Comunidad Escuela Vue

Comunidad Escuela Vue