0

I am trying to post a thread using node.js If I have any media attached to a tweet, I need to upload it and store the uploadedId which is in my case mediaId. I am getting the mediaId inside a forEach loop, if I want to use it inside the forEach the value is available. But, I want to store the id into an array and access it while calling another method that is outside the forEach loops.

Below is the code I tried,

var tweets = post['thread'] 
tweets.forEach((tweet,index)=>{
    if(tweet['media']!=undefined){
        var files = tweet['media']['media_ids'] //Initially I stored the filenames in media_ids Array, later I am updating it with MediaId
        tweets[index]['media']['media_ids'] = []
        files.forEach(async(file)=>{
            var file = './public/images/'+files[0]
            const mediaId = await tClient.v1.uploadMedia(file);
            tweets[index]['media']['media_ids'].push(mediaId)
            console.log(tweets[index][media]['media_ids]) //Output: ['123456789'] This is the output I need.
        })
     }
})
console.log(tweets[0]['media']['media_ids']) //Output: [] This is the output I am getting.

I hope my problem is clear to you, please help me!

Sujith Kumar
  • 872
  • 6
  • 19
AKC
  • 13
  • 1

3 Answers3

0

The array.forEach does not wait to move to the next iteration after each async code execution is completed, instead for this context use for-in or Where loops

0

You could use an async function with for...of loops instead. forEach is not designed to work with Promises.

async function doSomething() {
    const tweets = post.thread;
    for (const [index, tweet] of tweets.entries()) {
        if (tweet.media != null) {
            tweets[index].media.media_ids = [];
            // Promise.all with Array#map could also be used here
            for (let file of tweet.media.media_ids) {
                file = './public/images/' + file; 
                // assuming you meant to use the current file, not always the first file
                const mediaId = await tClient.v1.uploadMedia(file);
                tweets[index].media.media_ids.push(mediaId);
            }
        }
    }
}
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
  • Hi @Unmitigated!, I tried your code, but it still returns an empty array. Assume this is my array: [ { text: "Hi There!", media: { media_ids: ['bun.png'] } } ] Could you check it with this data, please? – AKC Apr 08 '23 at 18:42
  • @AKC How are you using it? Are you accessing the array inside the async function? – Unmitigated Apr 08 '23 at 18:44
  • Yes! I am using the above code inside an async callback function which is inside the forEach of a cursor object(result of db) and again it is inside an async function. I am worried, am I doing it in a wrong way? – AKC Apr 08 '23 at 18:58
  • @AKC Can you send a portion of your code? If you're still putting async code inside `forEach`, it's not going to wait for any of it to finish (as I mentioned in my answer). – Unmitigated Apr 08 '23 at 19:08
  • Hi @Unmitigated below is the code I am using [link](https://pastebin.mozilla.org/MZUdMGnc) – AKC Apr 09 '23 at 05:51
  • @AKC Replace the `forEach` with a `for...of` loop as well. – Unmitigated Apr 09 '23 at 06:04
  • Hi @Unmitigated, Thanks for your help, I saw that in the code, we mistakenly emptied the array and iterated the array. So, the file was never uploaded and returned []. Thanks for your help, I am glad you helped me :) – AKC Apr 09 '23 at 08:37
-1
var tweets = post['thread'] 
tweets.forEach((tweet,index)=>{
if(tweet['media']!=undefined){
    var files = tweet['media']['media_ids']
    tweets[index]['media']['media_ids'] = []
    Promise.all(files.map(async file =>{
        var file = './public/images/'+files[0]
        const mediaId = await tClient.v1.uploadMedia(file);
        tweets[index]['media']['media_ids'].push(mediaId)
        console.log(tweets[index][media]['media_ids']) 
    }))
 }
})
console.log(tweets[0]['media']['media_ids'])

You can use the Promise.all() method to ensure that all the asynchronous operations in your code are completed before proceeding with any further operations. The Promise.all() method takes an array of promises as its argument and returns a single promise that resolves when all the promises in the array are resolved. In your case, you can use the Promise.all() method to wait for the uploadMedia() operations to complete before logging the output of the tweets[0]['media']['media_ids'] array.

try this.

  • Hi Manthan! I tried your code, but it didn't work for me could you check that with the below sample array [ { 'text': 'Hi there', 'media':{ 'media_ids':['bun.png']} } ] – AKC Apr 08 '23 at 18:54