Estoy tratando de guardar los datos del usuario cuando se activa el evento de JavaScript "antes de descargar". Llamo a una función del lado del servidor (funciones de nube de firebase) que simplemente obtiene un objeto del usuario y actualiza un documento. La función se activa, pero desde la consola de firebase puedo verla terminada con el código 204. Aquí está mi código de cliente
window.onbeforeunload = function() { firefun_ref(data); }Lado del servidor:
exports.updateStats = functions.https.onCall(async (data, context) => { return admin.firestore().collection("stats") .doc((new Date()).toISOString().substring(0, 10)) .update(filter(data)); });Quiero señalar que si ejecuto la función sola, funciona bien, solo da problemas cuando está en el evento anterior a la descarga.
Esto no será posible.
Los navegadores limitan severamente lo que se le permite hacer en un evento beforeunload a la descarga, porque es muy propenso al abuso. Los eventos asincrónicos no están permitidos (porque podrían obligar a la ventana a permanecer abierta durante un tiempo arbitrario después de que el usuario quiera cerrarla).
Hasta donde yo sé, el único uso confiable de onbeforeunload es mostrar un mensaje que le permite al usuario cambiar de opinión; algunos navegadores le permitirán personalizar el texto que aparece (devolviendo una cadena del controlador beforeunload ), algunos navegadores siempre mostrarán el texto predeterminado:
window.addEventListener('beforeunload', function (e) { // Cancel the event e.preventDefault(); // If you prevent default behavior in Mozilla Firefox prompt will always be shown // Chrome requires returnValue to be set e.returnValue = ''; });https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload
Estoy tratando de hacer que esto funcione con Beacon API e incluso encontré un gancho:
/* see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon ```jsx const MyComponent = ({ children }) => { // will get fired if the page unloads while the component is mounted useUnloadBeacon({ url: 'https://api.my.site/route', payload: () => { return 'something' } }) return children } ``` */ import { useEffect } from "react" export const useUnloadBeacon = ({ url = "", payload = () => {}, }) => { const eventHandler = () => navigator.sendBeacon(url, payload()) useEffect(() => { window.addEventListener("unload", eventHandler, true) return () => { window.removeEventListener("unload", eventHandler, true) } }, []) }El único problema al que me enfrento es activar la función de nube. Estoy enviando una solicitud de obtención, pero de alguna manera no se activa.
app.post("/setStatusToOpen", setStatusToOpen) const setStatusToOpen = async (req, res) => { console.log("setStatusToOpen, req.query", req.query) const { documentId } = req.query try { const setPayload = { status: "open" } firestore .doc(`messageInABottle/${documentId}`) .set(setPayload, { merge: true }) return res.send(true) } catch (error) { console.log("Error in getMessageInABottleRecipient:", error) return res.send(error) } }Creo que tiene algo que ver con que los encabezados no estén bien.
Si los datos que desea escribir se conocen antes de que el usuario cierre la pestaña, puede registrar un controlador denominado onDisconnect en Realtime Database (la otra base de datos que forma parte de Firebase).
Un controlador onDisconnect es una operación de escritura retrasada que se ejecuta tan pronto como el servidor nota que el cliente se ha desconectado, ya sea porque el SDK en ese cliente le indica antes de desconectarse o porque el socket expira en el servidor (lo que puede demorar unos minutos). ).
No existe un equivalente en Firestore, porque su protocolo de conexión no tiene conexión, mientras que Realtime Database funciona en base a sockets (web). Sin embargo, si desea integrar esto en Firestore, eche un vistazo a la documentación sobre cómo crear un sistema de presencia en Firestore mediante el uso de Realtime Database .