functions-samples icon indicating copy to clipboard operation
functions-samples copied to clipboard

get list of document in function*

Open hathemi opened this issue 6 years ago • 2 comments

How to reproduce these conditions

Sample name or URL where you found the bug

Failing Function code used (including require/import commands at the top)

Steps to set up and reproduce

Sample data pasted or attached as JSON (not an image)

Security rules used

Debug output

Errors in the console logs

Screenshots

Expected behavior

Actual behavior

hathemi avatar Jan 27 '19 10:01 hathemi

> exports.notifyNewMessage = functions.firestore
>     .document('container/{container_id}').onWrite((change,context) => {
>     const newValue = change.after.data();
>     const previousValue = change.before.data();
>         const location=[];
> 
>         admin.firestore().collection('driver')
>         .get()
>         .then(snapshot => {
>           snapshot.forEach(doc => {
>                 location=doc.data().location;
>                 })
>               })
>      var nearestDriver =  NearestDriver( newValue.location._latitude, newValue.location._longitude);
>       return admin.firestore().collection('tokens').doc(uid).get().then(doc => {
>          })
> }

i connot get list of locations. i always get undefined. did i miss something??

hathemi avatar Jan 27 '19 11:01 hathemi

First, you cannot define a const more than once:

const location = [];  //  location is []

location = doc.data().location // TypeError: invalid assignment to const 'location'

To fix this, change const location to var location as variables defined with var can be redefined. You can read more about declarations here.

Second, you are accessing location before the promise resolves with the date from firestore. Instead, place your code that relies on location in the callback for the firestore read:

// Here, location = [];

admin.firestore().collection('driver')
  .get()
  .then(snapshot => {

    snapshot.forEach(doc => {
      location = doc.data().location;
    });

    // Use `location` here

  });

// Here, location = []

This way, the code that relies on location will only run once the locations have been retrieved.

(Also, you should probably move the declaration of location to a more appropriate scope):

// Old placement:
// var location = [];

admin.firestore().collection('driver')
  .get()
  .then(snapshot => {

    // New placement:
    var location = [];  // Code within this callback will still be able to access this
    snapshot.forEach(doc => {
      location = doc.data().location;
    });

    // Use `location` here

  });

Third, if you are retrieving more than one document, it looks like you are iterating over the documents wrong; For each document, you are overriding the location you just stored:

// First loop:
 location = doc.data().location; // location = "location1"

// Second loop:
 location = doc.data().location; // location = "location2"

At the end of the loop, location is only equal to the last value. If you want to store an array of locations, you can do the following:

snapshot.forEach(doc => {
  location.push(doc.data().location);
});

You can read about .push() here.

Now location will be an array of locations. Of course, if you only want location to be the location field of the last document in the snapshot, you can disregard this point.

Finally, if you implement point two, you will have to move your return statements:

exports.notifyNewMessage = functions.firestore
  .document('container/{container_id}').onWrite((change, context) => {
    const newValue = change.after.data();
    const previousValue = change.before.data();
    var location - [];

    return /* <= notice this new return statement */ admin.firestore().collection('driver')
      .get()
      .then(snapshot => {
        snapshot.forEach(doc => {
          location = doc.data().location;
        })
        // Use location here
      })
  });

You can read more about: asynchronous javascript in general here, using javascript promises here, and the different ways to termenate cloud functions here (recommended).

I hope this was helpful.

CamWass avatar Feb 03 '19 12:02 CamWass