Estoy luchando para forzar el código para que sea sincrónico. El código está destinado a cargar una imagen usando un vue componible, esperar a que la carga se realice correctamente y luego almacenar la URL del almacenamiento de Firebase en una base de datos. Lo mejor que puedo hacer es hacer que el código funcione, pero el código de éxito se activa antes de que se complete la carga (aunque obtengo la URL).
El siguiente código no funciona, pero es mi intento de tratar de encadenar las acciones usando luego devoluciones de llamada para forzarlas a comportarse de manera sincrónica. No funciona.
VueComponent.vue
const newImage = async () => { if (image.value) { await uploadImage(image.value); } else return null; }; const handleSubmit = async () => { try { const colRef = collection(db, "collection"); newImage() .then(() => { addDoc(colRef, { content: content.value }); }) .then(() => { //code to run only on success }); }); } catch (error) { } };useStorage.js componible
import { ref } from "vue"; import { projectStorage } from "../firebase/config"; import { uploadBytesResumable, getDownloadURL, ref as storageRef, } from "@firebase/storage"; const useStorage = () => { const error = ref(null); const url = ref(null); const filePath = ref(null); const uploadImage = async (file) => { filePath.value = `${file.name}`; const storageReference = storageRef(projectStorage, filePath.value); //<--I want this to be synchronous, but it isn't. const uploadTask = uploadBytesResumable(storageReference, file); uploadTask.on( "state_changed", (snapshot) => { const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100; console.log("Upload is " + progress + "% done"); }, (err) => { }, () => { getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {console.log("File available at", downloadURL); }); } ); }; return { url, filePath, error, uploadImage }; }; export default useStorage;Su uploadImage no espera a que se complete la carga, por eso addDoc ocurre antes de lo que desea.
const uploadImage = async (file) => { filePath.value = `${file.name}`; const storageReference = storageRef(projectStorage, filePath.value); const uploadTask = uploadBytesResumable(storageReference, file); await uploadTask; // 👈 Wait for the upload to finish const downloadURL = getDownloadURL(uploadTask.snapshot.ref) return downloadURL; }Ahora puedes llamarlo con:
newImage() .then((downloadURL) => { addDoc(colRef, { content: content.value }); }) O, usando await nuevamente, con:
const downloadURL = await newImage(); addDoc(colRef, { content: content.value });