Estoy usando Firebase Storage y estoy tratando de cargar todos los activos a través de una llamada de función. La única forma de obtener una URL de activos es llamar, getDownloadURL
lo que devuelve una promesa. Necesito llamar a esto para cada activo, pero no puedo hacerlo esperar a que se cumplan todas las promesas antes de continuar por alguna razón.
Pensé que devolver una promesa mergeMap
haría esperar a todos, pero ese no parece ser el caso.
He mirado una serie de preguntas con respecto a las promesas y RXJS, pero parece que no puedo averiguar qué está mal con el código.
getAssets() {
return this.authService.user$.pipe(
first(),
switchMap(user => defer(() => from(this.afs.storage.ref(`${user.uid}/assets`).listAll()))),
switchMap(assets => from(assets.items).pipe(
mergeMap(async (asset) => {
return new Promise((res, rej) => {
asset.getDownloadURL().then(url => {
const _asset = {
name: asset.name,
url,
};
this.assets.push(_asset);
res(_asset);
})
.catch((e) => rej(e));
});
}),
)),
map(() => this.assets),
);
}
...
this.getAssets().subscribe(assets => console.log(assets)); // this runs before all asset's url has been resolved
Solución del problema
const { from } = rxjs
const { mergeMap } = rxjs.operators
const assets = [1,2,3,4,5]
function getUrl (index) {
return new Promise((res) => {
setTimeout(() => res(`http://example.com/${index}`), Math.random() * 3 + 1000)
})
}
// add param2 1 for mergeMap === concatMap
from(assets).pipe(
mergeMap(asset => {
return getUrl(asset)
}, 1)
).subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.5/rxjs.umd.min.js"></script>
No hay comentarios:
Publicar un comentario