Cloud Firestore 函数触发器和事务 - 如何正确返回承诺

时间:2021-05-31 09:21:32

标签: google-cloud-firestore async-await triggers google-cloud-functions

我有一个 Cloud Firestore 函数触发器“onCreate”。根据给定字段的值,我希望它通过事务更新一些文档并将创建的文档复制为 Algolia 中的记录,或者执行完全不同的事务。因此有几个条件,我不确定我是否正确返回承诺,因为有时函数没有按预期复制 Algolia 中的记录。

我粘贴了代码的简化版本,以防有人可以提供帮助。

exports.createArticle = functions.firestore.document('articles/{articleId}').onCreate(async (snap, context) => {
    
  const newDocData = snap.data()

  if(newDocData) {
    const userCreatorId = newDocData.createdBy
    const userDocRef = imported.db.collection('users').doc(userCreatorId)

    if(newDocData.type === 1) {

      newDocData.objectID = newDocData.id
      indexAlgolia.saveObject(newDocData)
      .then(() => {
        console.log('Article saved in Algolia with id:', newDocData.objectID )
      })
      .catch(err => {
        console.log('ERROR while ADDING object inAlgolia:', err)
      })

      return imported.db.runTransaction(async t => {
        // do some work
        const userDoc = await t.get(userDocRef)
        const userData = userDoc.data()
        if (userData && userData.field1 > 0) {
          t.update(userDocRef, {field2: true})
        }
      }).then(result => {
        console.log('Transaction success')
      }).catch(err => {
        console.log('Transaction failure:', err)
      })
    } 
    else {
      const colOneRef = imported.db.collection('colOne')
      colOneRef.where('field2', '==', newDocData.field3).limit(1).get().then(snapshot => {
        return imported.db.runTransaction(async t => {
          if (snapshot.empty) {  
            t.update(userDocRef, {field3: false})
          }
          const decrement = imported.fieldValue.increment(-1)
          t.update(userDocRef, {field4: decrement})
        }).then(result => {
          console.log('Transaction success')
        }).catch(err => {
          console.log('Transaction failure:', err)
        })
      }).catch(() => 'Error while querying colOneRef')
    }
  } 
})

1 个答案:

答案 0 :(得分:1)

当您有多个 async/then 调用时,您可以让它们等待结果并运行它们,就好像它们是同步的一样,但是从您的代码中我看到第二个不依赖于第一个,因此您可以将它们放入Promse.all() 使函数完成得更快,因为它们将并行运行。您的代码如下所示:

xports.createArticle = functions.firestore
  .document("articles/{articleId}")
  .onCreate(async (snap, context) => {
    const newDocData = snap.data();

    if (newDocData) {
      const userCreatorId = newDocData.createdBy;
      const userDocRef = imported.db.collection("users").doc(userCreatorId);

      if (newDocData.type === 1) {
        newDocData.objectID = newDocData.id;
        const firstPromise = indexAlgolia
          .saveObject(newDocData)
          .then(() => {
            console.log(
              "Article saved in Algolia with id:",
              newDocData.objectID
            );
          })
          .catch((err) => {
            console.log("ERROR while ADDING object inAlgolia:", err);
          });

        const secondPromise = imported.db
          .runTransaction(async (t) => {
            // do some work
            const userDoc = await t.get(userDocRef);
            const userData = userDoc.data();
            if (userData && userData.field1 > 0) {
              t.update(userDocRef, { field2: true });
            }
          })
          .then((result) => {
            console.log("Transaction success");
          })
          .catch((err) => {
            console.log("Transaction failure:", err);
          });

        return Promise.all([firstPromise, secondPromise]);
      } else {
        const colOneRef = imported.db.collection("colOne");
        return colOneRef
          .where("field2", "==", newDocData.field3)
          .limit(1)
          .get()
          .then((snapshot) => {
            return imported.db
              .runTransaction(async (t) => {
                if (snapshot.empty) {
                  t.update(userDocRef, { field3: false });
                }
                const decrement = imported.fieldValue.increment(-1);
                t.update(userDocRef, { field4: decrement });
              })
              .then((result) => {
                console.log("Transaction success");
              })
              .catch((err) => {
                console.log("Transaction failure:", err);
              });
          })
          .catch(() => "Error while querying colOneRef");
      }
     return
    }
  });