Tengo que fusionar tres matrices en una matriz de objetos, donde cada objeto i contiene el valor i de cada matriz.
Tengo tres matrices que contienen datos de firebase (matrices de URL para miniaturas, URL para imágenes de tamaño completo y objetos con metadatos.
let finalArrayOfImagesAndMetadata = []; // Getting array of download url's for every file const getDownloadUrlFullFile = await Promise.all(getAllFilesList.items.map(itemRef => getDownloadURL(itemRef))); const getDownloadUrlThumbnails = await Promise.all(getAllThumbnails.items.map(itemRef => getDownloadURL(itemRef))); // Getting metadata for all files const getMetadataForAllFiles = await Promise.all(getAllFilesList.items.map(itemRef => getMetadata(itemRef)));He logrado desarrollar dos formas de resolver este problema:
primero:
// Merging full size image url, thumbnail url and metadata in one object const processArray = async () => { getDownloadUrlFullFile.forEach((o)=>{ finalArrayOfImagesAndMetadata.push({'fullImageUrl': o}); }); getDownloadUrlThumbnails.forEach((x, i)=>{ finalArrayOfImagesAndMetadata[i].imageUrl =x; }) getMetadataForAllFiles.forEach((x, i)=>{ const element = x.customMetadata; finalArrayOfImagesAndMetadata[i] = {...finalArrayOfImagesAndMetadata[i], ...element}; }) console.log(finalArrayOfImagesAndMetadata) return finalArrayOfImagesAndMetadata; }segundo:
// Merging full size image url, thumbnail url and metadata in one object const processArray = async () => { return new Promise(async function (resolve, reject) { for (let i =0 ; i<getDownloadUrlFullFile.length; i++){ const getSpecificFileThumbnail = getDownloadUrlThumbnails[i]; const getFileMetadata = loadedMetaData[i].customMetadata; const imageUrl = {'imageUrl': getSpecificFileThumbnail}; const fullImageUrl = {'fullImageUrl': getDownloadUrlFullFile[i]} finalArrayOfImagesAndMetadata.push({...getFileMetadata, ...imageUrl, fullImageUrl}); if ( finalArrayOfImagesAndMetadata.length === getDownloadUrlThumbnails.length) { return (finalArrayOfImagesAndMetadata); } resolve (finalArrayOfImagesAndMetadata); }})}Ambas soluciones funcionan pero, ¿hay alguna forma mejor y más sofisticada de resolver esto? ¿Tal vez algo con esperar hasta que se complete cada paso de escritura en la matriz?
Otras palabras: ¿cómo hacerlo como un profesional?
Sí, algunas formas dependiendo de la forma deseada de los datos resultantes...
const urls = await Promise.all(getAllFilesList.items.map(itemRef => getDownloadURL(itemRef))); const thumbnails = await Promise.all(getAllThumbnails.items.map(itemRef => getDownloadURL(itemRef))); const metadata = await Promise.all(getAllFilesList.items.map(itemRef => getMetadata(itemRef))); // simplest merge is just a concatenation const oneBigArray = [...urls, ...thumbnails, ...metadata] // another sort of merge is to have the arrays as props in an object const oneBigObject = { urls, thumbnails, metadata }; // notice no spread ... operatorUna verdadera "fusión" se activaría a partir de algo común en cada uno de los objetos de las matrices para crear una matriz de objetos como:
[ { key: 'some common key', url: 'some url', thumbnail: 'some url', metadata: { /* some meta data object */ } }, // ... ];Elaborar aquí requiere saber más sobre los objetos devueltos, por ejemplo, si hay una clave en cada uno de los objetos devueltos que los vincula a sus amigos en las otras matrices.
Puede iterar sobre los elementos como su primera opción, pero use el método de mapa para construir la nueva matriz. Luego puede usar el argumento de índice para obtener los otros datos (como su segunda opción), así:
const mergedArray = getDownloadUrlFullFile.map((fullImageUrl, i)=>({ // Shorthand to set fullImageUrl: fullImageUrl fullImageUrl, // assign the property directly 'imageUrl': getSpecificFileThumbnail[i], // You can also spread values if you want them directly on the object {...loadedMetaData[i].customMetadata} }));Si desea combinar las solicitudes y la fusión de datos, puede usar el patrón Promise.all y Promise.map https://www.techiediaries.com/promise-all-map-async-await-example/
@danh
// simplest merge is just a concatenation const oneBigArray = [...urls, ...thumbnails, ...metadata]¡Esto se ve genial! ¿Alguna forma de agregar una clave a cada '... URL' para tener todas las URL como esta?
{imageUrl: www...., thumbnailUrl: www..., metadata : {} }@Assaf
También me gusta mucho tu enfoque. No pensé que pudiera usar el iterador para cada matriz en una sola pasada, buena.
Gracias a todos. Definitivamente acortaré el código.