简体   繁体   中英

Firebase Cloud Functions - TypeError: Cannot read property 'data' of undefined when data exists

I have the following cloud function:

exports.keepPostKeysUpdated = functions.database.ref('/posts/{postid}').onWrite(event => { 
  console.log("write on posts...");
  console.log(event.previous.params.postID);
  console.log(event.data.previous.val());
  console.log(event.data.previous.val().postID);
  var postKey = event.data.previous.val().postID;


  // When a table, category, or region is changed the old upload has to be deleted
  if (event.data.previous.exists()) {
    if (event.data.previous.val().table != event.data.val().table || event.data.previous.val().region != 
        event.data.val().region || event.previous.data.val().category != event.data.val().category) {
          // category, region, or table was changed
          console.log(postKey);
          if (event.data.previous.val().table != event.data.val().table) {
            console.log("Table was changed");
            // delete the post from the old table
            const oldTable = event.data.previous.val().table;
            const newTable = event.data.val().table;

            addToNewTable(newTable, postKey);
            removePostFromOldTable(oldTable, postKey);
          }
          if (event.data.previous.val().category != event.data.val().category) {
            console.log("Category was changed");
            // delete the post from the old category
            const oldCategory = event.data.previous.val().category;
            const newCategory = event.data.val().category;

            addToNewCategory(newCategory, postKey);
            removePostFromOldCategory(oldCategory, postKey);
          }
          if (event.data.previous.val().region != event.data.val().region) {
            console.log("Region was changed");
            // delete post from old region
            const oldRegion = event.data.previous.val().region;
            const newRegion = event.data.val().region;

            addToNewRegion(newRegion, postKey);
            removePostFromOldRegion(oldRegion, postKey);
          }  
        }
        else {
          return
        }
}
else {
  // previous value does not exist this case is handled by 
  // copyPostKey
  return
}
});

It work perfectly fine when a table or region is changed but fails every time a category is changed. The error is coming from the line var postKey = event.data.previous.val().postID; How can this value be read some times but not others? I can even console log the key, but it says it can't be read when I try to assign it to postKey. Any idea what this issue is from?

The data is always written the same way from my iOS app

ref.child("posts").child(editedPost.postID).updateChildValues(["table": editedPost.table])
ref.child("posts").child(editedPost.postID).updateChildValues(["category": editedPost.category])
ref.child("posts").child(editedPost.postID).updateChildValues(["region": editedPost.region])

node = v6.11.2 firebase-tools = 3.10.10

previous.val() only works if the previous value exists. It may not exist if this is the first write for that path. You should check to see if it exists before referencing it:

event.data.previous.exists()

https://firebase.google.com/docs/database/extend-with-functions#reading_the_previous_value

In addition to Matts answer, you need to adjust your logic.

exports.keepPostKeysUpdated = functions.database.ref('/posts/{postid}').onWrite(event => { 
  // When a table, category, or region is changed the old upload has to be deleted
  if (event.data.previous.exists()) {
      var postKey = event.data.previous.val().postID;

If you check the postKey after the event.data.previous.exists() statement you shouldn't have any problems.

It might be worth looking at the Firebase Documentation , they have different triggers depending on the write operation;

onWrite() , which triggers when data is created, destroyed, or changed in the Realtime Database.

onCreate() , which triggers when new data is created in the Realtime Database.

onUpdate() , which triggers when data is updated in the Realtime Database.

onDelete() , which triggers when data is deleted from the Realtime Database.

In your case, you could change your logic to use onUpdate

exports.keepPostKeysUpdated = functions.database.ref('/posts/{postid}').onUpdate(event => { 
  var currentValue = currentValue;
  var previousValue = previousValue;
  var postKey = previousValue.postID;


  // When a table, category, or region is changed the old upload has to be deleted
    if (previousValue.table != currentValue.table || previousValue.region != currentValue.region || event.previous.data.val().category != currentValue.category) {
      // category, region, or table was changed
      console.log(postKey);
      if (previousValue.table != currentValue.table) {
        console.log("Table was changed");
        // delete the post from the old table
        const oldTable = previousValue.table;
        const newTable = currentValue.table;

        addToNewTable(newTable, postKey);
        removePostFromOldTable(oldTable, postKey);
      }
      if (previousValue.category != currentValue.category) {
        console.log("Category was changed");
        // delete the post from the old category
        const oldCategory = previousValue.category;
        const newCategory = currentValue.category;

        addToNewCategory(newCategory, postKey);
        removePostFromOldCategory(oldCategory, postKey);
      }
      if (previousValue.region != currentValue.region) {
        console.log("Region was changed");
        // delete post from old region
        const oldRegion = previousValue.region;
        const newRegion = currentValue.region;

        addToNewRegion(newRegion, postKey);
        removePostFromOldRegion(oldRegion, postKey);
      }  
    } else {
      return
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM