我必须将三个数组合并为一个对象数组,其中每个I对象都包含每个数组中的值I。
我有三个数组,其中包含来自firebase的数据(缩略图的url数组、全尺寸图像的url数组和带有元数据的对象数组(
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)));
我已经设法开发了两种解决这个问题的方法:
第一个:
// 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;
}
第二:
// 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);
}})}
这两种解决方案都有效,但是,有没有更复杂、更好的方法来解决这个问题?也许需要等待,直到写入数组的每一步都完成?
换句话说:如何像专业人士一样做到这一点?
您可以像第一个选项一样迭代元素,但使用map方法来构造新数组。然后你可以使用index参数来获取其他数据(就像你的第二个选项(,所以:
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}
}));
如果要将请求和数据合并在一起,可以使用Promise.all和Promise.map模式https://www.techiediaries.com/promise-all-map-async-await-example/
是的,有几种方法取决于结果数据的所需形状。。。
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 ... operator
一个真正的";合并";将关闭数组中每个对象中的一些共同点,以构建一个对象数组,如:
[
{ key: 'some common key',
url: 'some url',
thumbnail: 'some url',
metadata: { /* some meta data object */ }
},
// ...
];
这里的详细说明需要了解更多关于返回对象的信息,例如,如果每个返回对象中都有一个键,将它们与其他数组中的朋友联系起来。
@danh
// simplest merge is just a concatenation
const oneBigArray = [...urls, ...thumbnails, ...metadata]
这看起来很酷!任何将密钥添加到每个"…"的方法。。。url";,拥有这样的所有url?
{imageUrl: www....,
thumbnailUrl: www...,
metadata : {}
}
@Assaf
我也很喜欢你的做法。我不认为我可以在一次遍历中对每个数组使用迭代器,这很好。
谢谢大家。我会毫不留情地缩短代码。