0

I have a an array of a number of N paths to retrieve data from a different location in firebase database.

searchPaths = ['locations/date1/imageID', 'locations/date2/imageID2', locations/date3/imageID3, ...]

now, I want to loop through each search path and pull a value from it to save an array of image URL's.

    const searchPaths = ['locations/date1/imageID', 'locations/date2/imageID2']
    const imageURLs = []

     for(var Obj in searchPaths) 
    {
        const path = Obj
        admin.database().ref(path).once('value').then(snapshot => 
        { 
        const URL = snapshot.val().fileURL;
        imageURLs.push(URL);
        console.log('ImageURL: ' + URL );
        })
    // here is where it gets sour
    }.then(() => {
        console.log("All image URL's" + imageURLs")
    }

So, my question is, how do I return a promise when we have now pulled the data we need from every ref? is there a Promise.all type? where does it go?

2 Answers 2

1

You can use the for-loop to create an array of promises, then use Promise.all, crude I know but it should work.

const searchPaths = ['locations/date1/imageID', 'locations/date2/imageID2']
const imageURLs = []
var promises = [];
 for(var Obj in searchPaths) 
{
    promises.push(new Promise(function(resolve, reject) {
      const path = Obj
      admin.database().ref(path).once('value').then(snapshot => 
      { 
      const URL = snapshot.val().fileURL;
      imageURLs.push(URL);
      console.log('ImageURL: ' + URL );

      //resolve the promise after pushing imageURL
      resolve();
      })
    }));
}

//when all of them are done:
Promise.all(promises)
.then(function(results) {
  //code when done...
})
Sign up to request clarification or add additional context in comments.

2 Comments

A Promise object has three states: pending, resolved, and reject. Any Promise object is built with a function with two parameters: the resolve and reject functions. When the resolve is called, the promise will resolve, and return a value, and similarly with reject, but in reject's case an error will be thrown. In this code, we are essentially leaving the promise in the "pending" state until we call resolve to resolve the promise when the images are loaded. We then fill an array with these promises, then use them in Promise.all, which waits for all promises to resolve.
There's too much work going on here. once() returns a promise, so there's no need to create a new promise object each time. Please see my answer here for a shorter and more elegant solution.
1

The other answer here is going through too much trouble to collect promises. It's easier to just push the return value of once() into the promises array rather than creating a new promise each time.

const searchPaths = ['locations/date1/imageID', 'locations/date2/imageID2']
const imageURLs = []
const promises = []   // collect promises here

searchPaths.forEach(path => {
    promises.push(admin.database().ref(path).once('value'))
})

Promise.all(promises).then(results => {
    results.forEach(snapshot => {
        const URL = snapshot.val().fileURL;
        imageURLs.push(URL);
        console.log('ImageURL: ' + URL );
    }
})

The then callback on the promise returned from Promise.all() will be an array of all the snapshots from the queries pushed into the promises array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.