swift - 执行异步 Cloud Function 的问题

标签 swift firebase firebase-cloud-messaging google-cloud-functions

我的数据库是这样的

enter image description here

我的云函数是

// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');

// The Firebase Admin SDK to access the Firebase Realtime Database.
const admin = require('firebase-admin');
admin.initializeApp();

exports.userGotNewMessage = functions
.region(`europe-west1`)
.database
.ref(`user-messages/{userId}/{senderId}/{messageId}`)
.onCreate((snap, context) => {
  var userId = context.params.userId
  console.log(`Step 1  ${userId}`)
  var text = snap.val().text
  var toId = snap.val().toId
  var numberOfUnreadMessages = 0
  var db = admin.database()

  if (userId === toId) {
    console.log(`Step 2 ${userId}`)
  var unreadMessagesRef = db.ref(`unread-messages/${userId}`)
  unreadMessagesRef.on("value", (snap) => {
    snap.forEach((childNode) => {
      var nodeNumber = childNode.val().numberOfUnreadMessages
      numberOfUnreadMessages = numberOfUnreadMessages + nodeNumber
    })
    return console.log(`Found ${numberOfUnreadMessages} unread messages for ${userId}`)
  });

  console.log(`Step 3 ${userId}`)
  var token = 'dxfAkmce.....my testing device'
  console.log(text)
  var message = {
    "token": String(token),
    "data": {
      "count": `${numberOfUnreadMessages}`
    }
  }

  admin.messaging().send(message)
  .then((response) => {
    console.log(`Step 4 ${userId}`)
    // Response is a message ID string.
    return console.log('Successfully sent message:', response);
    // detailed information about result if send succeded but something went wrong
    // console.log(response.results[0].error);
  })
  .catch((error) => {
    return console.log('Error sending message:', error);
  });
  }
  console.log(`Step 5 ${userId}`)
  return null
});

绑定(bind)使用这个函数我得到了奇怪的行为。发送消息后计算未读消息的数量等等,例如在开始后我从无处收到关于未读消息计数的消息(数据库中根本没有 16 条消息))) 控制台中有这样的东西

3:05:23.627 PM userGotNewMessage Successfully sent message: projects/chatapp-2e320/messages/1544015123460374

3:05:23.626 PM userGotNewMessage Step 4 VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.340 PM userGotNewMessage Function execution took 9 ms, finished with status: 'ok'

3:05:23.334 PM userGotNewMessage Step 5 nx9XfqgIqyS8PdZ8PzLQ9sEyKoV2

3:05:23.333 PM userGotNewMessage Step 1 nx9XfqgIqyS8PdZ8PzLQ9sEyKoV2

3:05:23.331 PM userGotNewMessage Function execution started

3:05:23.325 PM userGotNewMessage Function execution took 151 ms, finished with status: 'ok'

3:05:23.317 PM userGotNewMessage Step 5 VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.317 PM userGotNewMessage hello again

3:05:23.317 PM userGotNewMessage Step 3 VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.317 PM userGotNewMessage Found 1 unread messages for VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.234 PM userGotNewMessage Step 2 VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.234 PM userGotNewMessage Step 1 VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.182 PM userGotNewMessage Found 16 unread messages for VobaLy7AKMeYnGv7OgIokaeQ5UG2

3:05:23.175 PM userGotNewMessage Function execution started

我明白这是由异步工作引起的,但我无法自己修复它,因为我是一个完全的初学者。请帮我修复这个错误!!

最佳答案

正如@rijin 在他的回答中所说,您应该返回异步 send() 方法返回的 promise 。但是,同样重要,您不应在云函数结束时返回 null

通过返回 null,这将发生在 send() 返回的 promise 解决之前,您向 Cloud Function 表明工作已完成。因此,换句话说,云函数在异步作业完成之前停止执行。

此外,在 Cloud Function(具有相对“短”的生命周期)中使用 on() 监听器是不够的。你最好使用 once()方法。

最后,您显然在 Cloud Function 中实现了两个不同的业务逻辑部分,一部分用于报告未读消息的数量,另一部分用于发送消息。您应该在两个不同的 Cloud Functions 中执行此操作,或者链接异步方法返回的不同 promise (即 once()send() 方法)。

所以,对于消息发送部分,按照下面的方式应该是可行的:

exports.userGotNewMessage = functions
.region(`europe-west1`)
.database
.ref(`user-messages/{userId}/{senderId}/{messageId}`)
.onCreate((snap, context) => {
  var userId = context.params.userId
  console.log(`Step 1  ${userId}`)
  var text = snap.val().text
  var toId = snap.val().toId
  var numberOfUnreadMessages = 0
  var db = admin.database()


  console.log(`Step 3 ${userId}`)
  var token = 'dxfAkmce.....my testing device'
  console.log(text)
  var message = {
    "token": String(token),
    "data": {
      "count": `${numberOfUnreadMessages}`
    }
  }

  return admin.messaging().send(message);

});

如果您想在一个 Cloud Function 函数中链接 send()once() 方法,您可以按照以下几行进行操作:

return admin.messaging().send(message)
.then(messageID => {
    if (userId === toId) {
        var unreadMessagesRef = db.ref(`unread-messages/${userId}`);
        return unreadMessagesRef.once('value')
            .then(snap => {
                snap.forEach(childNode => {
                    var nodeNumber = childNode.val().numberOfUnreadMessages;
                    numberOfUnreadMessages = numberOfUnreadMessages + nodeNumber;
                });
                console.log(`Found ${numberOfUnreadMessages} unread messages for ${userId}`);
                return null;
            });
    } else {
        return null;
    }
});

关于swift - 执行异步 Cloud Function 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53633332/

相关文章:

firebase - 如果您不将参数添加到 Firebase Analytics 控制台,参数是否会被存储?

javascript - Ionic 3 - 使用异步数据更新 Observable

firebase - 如何修复我的 Application.java 以使用新版本的 Firebase_messaging

flutter :fcm ios 推送通知在 Release模式下不起作用

android - 已在 FCM 中注册主题的客户列表

swift - 如何添加到当前存储在用户默认值 Swift 4 中的数字

ios - 延迟覆盖 IBOutlet 对象的属性

swift - 闭包中 "self"指的是什么 - Swift

swift - 如何将 DispatchTimeInterval 转换为 NSTimeInterval(或 Double)?

ios - Firebase 和推送通知/云消息传递