sd_dewasurendra
sd_dewasurendra

Reputation: 393

How to call a function after map() loop executed

I'm using react-native firebase to save my media into firebase. I have a set of URLs that need to be saved in the firebase. For that, I'm using map() to save one by one. After saving I'm pushing the success URL to the array. I need to call a function with this array as a parameter. So I need to call this function after the array is completed. I have searched a lot but I did not find a good explanation for this task. Can anyone help me. Thank you.

var mediaArray = []; //array of success callbacks values
var completedMediaSurveysAnswers = [{}, {}, {}]; //object array of URLs and media types
completedMediaSurveysAnswers.map((i) => {
  try {
    const storage = firebase.storage();
    const mRef = storage.ref('portal').child('Survey/Image/user/' + uuidv4() + 'media');
    mRef.putFile(i.urlPath, {
        contentType: i.mediaType
      })
      .on('state_changed', snapshot => {},
        err => {
          console.log('Failed to upload file to firebase storage')
        },
        uploadedFile => {
          // Success
          this.setState({
            mediaPath: uploadedFile.downloadURL
          })
          mediaArray.push(this.state.mediaPath)
        });
  } catch (error) {
    console.log(error)
  }
})

//need to call this function after loop is done
saveAnswers(mediaArray)

Upvotes: 5

Views: 5743

Answers (4)

Hardik Desai
Hardik Desai

Reputation: 1217

As per my knowledge we can dom something like below.

Learn From : https://www.codegrepper.com/code-examples/javascript/wait+for+map+to+finish+javascript

Perform an action after .map() completion:

var promises = testUserArray.map((item, index) => {
    console.log('item', item)
})

await Promise.all(promises).then(() => {
    console.log('Map Opration Successfully Completed')
})

Example App:

import React, { useState } from 'react'
import { View, StatusBar, Text, Button } from 'react-native'

export default function App() {

    const [testUserArray, setTestUserArray] = useState(testArray)

    const _testMap = async () => {

        var promises = testUserArray.map((item, index) => {
            console.log('item', item)
        })

        await Promise.all(promises).then(() => {
            console.log('Map Opration Successfully Completed')
        })
    }
    return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', }}>
            <Button
                title='Test .map()'
                onPress={() => _testMap()}
            />
        </View>
    )
}

const testArray = [
    {
        "id": '1',
        "name": 'User 1'
    },
    {
        "id": '2',
        "name": 'User 2'
    },
    {
        "id": '3',
        "name": 'User 3'
    },
    {
        "id": '4',
        "name": 'User 4'
    },
    {
        "id": '5',
        "name": 'User 5'
    },
]

Upvotes: 1

Hamed Navvabian
Hamed Navvabian

Reputation: 792

You can use Promise or async/await to handle all kind of these situations like this:

var mediaArray = [];
var completedMediaSurveysAnswers = [{}, {}, {}];

async function handleYourTask() {
  await completedMediaSurveysAnswers.map((i) => {
  try {
    const storage = firebase.storage();
    const mRef = storage.ref('portal').child('Survey/Image/user/' + uuidv4() + 'media');
    mRef.putFile(i.urlPath, {
        contentType: i.mediaType
      })
      .on('state_changed', snapshot => {},
        err => {
          console.log('Failed to upload file to firebase storage')
        },
        uploadedFile => {
          // Success
          this.setState({
            mediaPath: uploadedFile.downloadURL
          })
          mediaArray.push(this.state.mediaPath)
        });
    } catch (error) {
      console.log(error)
    }
  })

  await saveAnswers(mediaArray);
}

and then you can call handleYourTask function anywhere you want :)

Upvotes: 3

Vibha Chosla
Vibha Chosla

Reputation: 713

Just check the length of your map array and compare it with map key.

Use async await to wait till file to upload

var mediaArray = []; //array of success callbacks values
var completedMediaSurveysAnswers = [{}, {}, {}]; //object array of URLs and media types
completedMediaSurveysAnswers.map(async (i, key) => {
  try {
    const storage = firebase.storage();
    const mRef = storage.ref('portal').child('Survey/Image/user/' + uuidv4() + 'media');
    await mRef.putFile(i.urlPath, {
        contentType: i.mediaType
      })
      .on('state_changed', snapshot => {},
        err => {
          console.log('Failed to upload file to firebase storage')
        },
        uploadedFile => {
          // Success
          this.setState({
            mediaPath: uploadedFile.downloadURL
          })
          mediaArray.push(this.state.mediaPath)
        });

     if( key == (completedMediaSurveysAnswers.length - 1 ) ){
       saveAnswers(mediaArray)
     }
  } catch (error) {
    console.log(error)
  }
})

I don't tested async await so use it wherever its set.

Upvotes: 0

Bravo
Bravo

Reputation: 6264

using .map is good, so you can return an Array of promises which you can then wait for their resolution

in this case, the resolved value in Promise.all will be what you were pushing into an array ... i.e. this.state.mediaPath

var completedMediaSurveysAnswers = [{}, {}, {}]; //object array of URLs and media types
var promises = completedMediaSurveysAnswers.map((i) => new Promise((resolve, reject) => {
    try {
        const storage = firebase.storage();
        const mRef = storage.ref('portal').child('Survey/Image/user/' + uuidv4() + 'media');
        mRef.putFile(i.urlPath, {
            contentType: i.mediaType
        }).on('state_changed', snapshot => {}, err => {
            console.log('Failed to upload file to firebase storage');
            resolve(null); // so one failure doesn't stop the whole process
        }, uploadedFile => {
            // Success
            this.setState({
                mediaPath: uploadedFile.downloadURL
            })
            resolve(this.state.mediaPath)
        });
    } catch (error) {
        console.log(error)
        resolve(null); // so one failure doesn't stop the whole process
    }
}));

//need to call this function after loop is done
Promise.all(promises).then(mediaArray => {
    saveAnswers(mediaArray);
});

Upvotes: 1

Related Questions