云功能有时会在触发另一个云功能后写入 FireStore

Posted

技术标签:

【中文标题】云功能有时会在触发另一个云功能后写入 FireStore【英文标题】:Cloud Function Sometimes Writes to FireStore AFTER another cloud function is triggered 【发布时间】:2021-09-14 17:57:48 【问题描述】:

我目前在处理某些仅在触发另一个实例后才写入的云功能时遇到问题。

我的云函数代码如下,由 pubsub 事件触发。

if (jsonData.Event == "TEST") 
  var msg = jsonData.Value;
  var timeOfReception = new Date();
  //changer l'occupation courante
  docRef
    .get()
    .then(function (doc) 
      if (doc.exists) 
        
       
        
        docRef.update(
          LastGesture: msg,

        ).then(function() 
        console.log("Write completed")
      ).catch(function(error) 
        console.error("Write failed: "+error)
      );       
     
       else 
        // doc.data() will be undefined in this case
        console.log("No such document!");
      
    )
    .catch(function (error) 
      console.log("Error getting document:", error);
    );
  

这是来自同一云功能的日志:


2021-07-02 15:44:17.869 EDTpubsubToFireStoregsn141ejhe1b Function execution started
Default
2021-07-02 15:44:17.874 EDTpubsubToFireStoregsn141ejhe1b Date: 2000/00/00-00:00:00, DeviceID: TSA00001, Event: TEST, Location: MAISON, Value: PRESENT, Version: 1.0, tableName: GestureTest
Debug
2021-07-02 15:44:17.875 EDTpubsubToFireStoregsn141ejhe1b Function execution took 7 ms, finished with status: 'ok'
Default
2021-07-02 15:44:18.532 EDTpubsubToFireStoregsn141ejhe1b Write completed
Debug
2021-07-02 16:04:27.466 EDTpubsubToFireStore2o6osfooylkj Function execution started
Default
2021-07-02 16:04:27.513 EDTpubsubToFireStore2o6osfooylkj Date: 2000/00/00-00:00:00, DeviceID: TSA00001, Event: TEST, Location: MAISON, Value: ABSENT, Version: 1.0, tableName: GestureTest
Debug
2021-07-02 16:04:27.548 EDTpubsubToFireStore2o6osfooylkj Function execution took 85 ms, finished with status: 'ok'
Debug
2021-07-02 16:05:40.824 EDTpubsubToFireStore2o6ozvzxeri1 Function execution started
Default
2021-07-02 16:05:41.347 EDTpubsubToFireStore2o6ozvzxeri1 Date: 2000/00/00-00:00:00, DeviceID: TSA00001, Event: TEST, Location: MAISON, Value: PRESENT, Version: 1.0, tableName: GestureTest
Debug
2021-07-02 16:05:41.351 EDTpubsubToFireStore2o6ozvzxeri1 Function execution took 528 ms, finished with status: 'ok'
Default
2021-07-02 16:06:07.130 EDTpubsubToFireStore2o6ozvzxeri1 Write completed
Default
2021-07-02 16:06:07.830 EDTpubsubToFireStore2o6ozvzxeri1 Write completed

如您所见,15:44:17 的函数完美运行:函数被触发并执行写操作。但是,16:04:27 的函数直到 16:05:41 的函数被触发才写入,正如它所显示的那样,这两个函数几乎同时写入。

我不确定如何解释这种行为,因为我还是云功能的新手。如果有什么可以为我指明正确的方向,我将不胜感激:)。如果需要,我可以提供更多详细信息。谢谢!

【问题讨论】:

【参考方案1】:

问题是在函数接收到(未定义的)返回值之前,您没有等待进程完成,因此函数在您的代码实际完成执行之前就完成了。

您必须await 以确保您的代码在返回之前完成。在这种情况下,您的整个函数将在 docRef.get() 之后返回。 .then() 中的代码被执行是偶然的,而不是因为你等待它。

当函数完成时,实例进入“暂停”状态。下次您调用函数时,同一个实例会“唤醒”。 到那时,前一次调用中的“待定”执行将完成运行,因为轮到它们时您没有给它们足够的时间来完成。

您可以通过时间戳和调用 id 注意到这一点:EDTpubsubToFireStore2o6ozvzxeri1 打印最后 2 个“写入完成”。此外,文本“Function execution taken [...]”应该是最后打印的内容,您打印的所有内容都应该出现在这一行之前。

您需要调整代码以等待整个执行后返回。比如:

exports.onWriteCol1 = functions.firestore.document('col1/id')
  .onWrite(async (change, context) => 
    /// whatever defines jsonData and docRef...
    if (jsonData.Event !== "TEST") 
      console.log('Nothing to do... leaving...');
      return;
    
    const msg = jsonData.Value;
    //changer l'occupation courante
    try 
      const snap = await docRef.get();
      if ( snap.exists ) 
        await docRef.update( LastGesture: msg );
        console.log("Write completed")
      
     catch (err) 
      console.error("Write failed: "+err);
    
  );

或者只是:

//changer l'occupation courante
await docRef.get().then(... return docRef.update() ... ).catch(...);

您需要返回update() 才能在上面返回await

(我不喜欢.then().catch() 接近xD,我猜是口味问题)

有关正确终止函数的更多详细信息:here。

======

顺便说一句,console.error("Write failed: "+err); 不会在 Firebase 函数日志中打印为错误,因为它是一个字符串。它必须是实际的new Error()。或者只使用console.error(err),因为err 已经是Error 的一个实例。

【讨论】:

哇,感谢您提供的详细答案,这对您有很大帮助!我会确保查看您提供的链接,了解如何终止函数的详细信息:)。

以上是关于云功能有时会在触发另一个云功能后写入 FireStore的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 云功能对 Xstate 没有任何作用

密码注册后 Firebase 云功能出现未经身份验证的错误

Firestore + 云功能:如何从另一个文档中读取

云功能不向 PubSub 发送消息

防止滥用:Firebase 的云功能

Firestore - 云功能 - 获取 uid