I'm currently working on iterating over an array of objects. Depending on the content of some of those objects, I need to execute a fetch function and wait for the result before updating the new array.
Below is my JavaScript code:
const allPosts = [
{
// Object details here...
},
// Additional object details...
];
let filteredPosts = [];
const output = document.querySelector('.output');
const parser = new DOMParser();
const setPostsByType = () => {
let doc;
let videoThumbnail = '';
for (let i = 0; i < allPosts.length; i++) {
const item = allPosts[i];
if (item.body) {
doc = parser.parseFromString(item.body, 'text/html');
}
if (item.type.includes('video')) {
let videoID = doc.querySelector('a')?.getAttribute('href')?.split('vimeo.com/')[1]
|| doc.querySelector('[data-url]')?.getAttribute('data-url')?.split('vimeo.com/')[1];
if (videoID && videoID.includes('?')) {
videoID = videoID.split('?')[0];
}
console.log(videoID);
fetch(`https://vimeo.com/api/v2/video/${videoID}.json`)
.then((response) => {
return response.text();
})
.then((data) => {
const { thumbnail_large } = JSON.parse(data)[0];
videoThumbnail = thumbnail_large + '.jpg';
console.log(videoThumbnail);
return videoThumbnail; // Asynchronous
})
.catch((error) => {
console.log(error);
});
}
const postObject = {
id: item.id,
post_id: `postid__${item.id}`,
body: item.body,
video_thumbnail_id: videoThumbnail,
type: item.type,
tags: item.tags,
date: item.date
};
filteredPosts.push(postObject);
}
};
setPostsByType();
output.textContent = JSON.stringify(filteredPosts, null, 4);
<pre class="output"></pre>
Apologies for the lengthy snippet. It's already a filtered set of data. For more information and a larger dataset, you can visit this JSFIDDLE link: https://jsfiddle.net/lharby/wrLpheok/.
The issue arises from the asynchronous nature of the fetch call. The ids of each video post get logged to the console after pushing to the filteredPosts array.
Several attempts have been made to address this issue:
- Enclosing everything within an async function.
- Creating a function that should return the postObject and executing it inside the fetch .then() function (however, this is wrapped in an if statement filtering items based on post type).
- Using a map instead of a for loop.
While there are solutions where users want to call a fetch API endpoint first and then map items, the situation here is different. The fetch function can only be called after iterating through each post body and meeting specific conditions.
Your assistance would be greatly appreciated.