【问题标题】:FCM and Typescript Async Await: Network Timing OutFCM 和 Typescript Async Await:网络超时
【发布时间】:2018-05-05 18:18:11
【问题描述】:

我是 Typescript 的新手,我正在尝试使用 async 和 await 功能。我每隔一段时间就会遇到一些 fcm 网络超时,我相信这与我没有正确返回我的承诺有关。

这是我用于发送推送通知的云功能。使用 await 关键字的两个函数是 incrementBadgeCountsendPushNotification

export const pushNotification = functions.firestore
  .document('company/{companyId}/message/{messageId}/chat/{chatId}')
  .onCreate(async event => {

const message = event.data.data();
const recipients = event.data.data().read;
const messageId = event.params.messageId;

const ids = [];
for (const key of Object.keys(recipients)) {
    const val = recipients[key];
    if (val === false) {
        ids.push(key);
    }
}

return await Promise.all(ids.map(async (id) => {
    const memberPayload = await incrementBadgeCount(id);
    const memberBadgeNumberString = 
      memberPayload.getBadgeCount().toString();

    const senderName = message.sender.name;
    const senderId = message.sender.id;
    const senderMemberName = message.senderMember.name;
    const toId = message.receiver.id;
    const text = message.text;
    const photoURL = message.photoURL;
    const videoURL = message.videoURL;
    const dealId = message.dealId;
    const dealName = message.dealName;

    const payload = {
        notification: {
          title: `${senderName}`,
          click_action: 'exchange.booth.message',
          sound: 'default',
          badge: memberBadgeNumberString
        },
        data: { senderId, toId, messageId }
    };

    const options = {
        contentAvailable: true
    }

    ........

    const deviceIDs = memberPayload.getDeviceID()
    return await sendPushNotification(id, deviceIDs, payload, options);
  }));
});

这里是 incrementBadgeCount 函数,它增加了有效负载的标记计数并返回了有效负载的一些信息:

async function incrementBadgeCount(memberID: string): 
  Promise<MemberPushNotificaitonInfo> {
const fs = admin.firestore();
const trans = await fs.runTransaction(async transaction => {
    const docRef = fs.doc(`member/${memberID}`);
    return transaction.get(docRef).then(doc => {
            let count: number = doc.get('badgeCount') || 0;
            const ids: Object = doc.get('deviceToken');
            transaction.update(docRef, {badgeCount: ++count});
            const memberPayload = new MemberPushNotificaitonInfo(count, ids);
            return Promise.resolve(memberPayload);
    });
});
return trans
}

最后是sendPushNotification 函数,它与 FCM 交互并发送有效负载并清除坏的设备令牌:

async function sendPushNotification(memberID: string, deviceIDs: string[], payload: any, options: any) {
if (typeof deviceIDs === 'undefined') {
    console.log("member does not have deviceToken");
    return Promise.resolve();
}

const response = await admin.messaging().sendToDevice(deviceIDs, payload, options);
const tokensToRemove = [];
response.results.forEach((result, index) => {
    const error = result.error;
    const success = result.messageId;
    if (success) {
        console.log("success messageID:", success);
        return 
    }
    if (error) { 
        const failureDeviceID = deviceIDs[index];
        console.error(`error with ID: ${failureDeviceID}`, error);

        if (error.code === 'messaging/invalid-registration-token' ||
            error.code === 'messaging/registration-token-not-registered') {
            const doc = admin.firestore().doc(`member/${memberID}`);
             tokensToRemove.push(doc.update({
                deviceToken: {
                    failureDeviceID: FieldValue.delete()
                }
            }));
        }
    }
});

return Promise.all(tokensToRemove);
}

我将不胜感激有关收紧此打字稿的一些帮助 :)

【问题讨论】:

    标签: typescript async-await firebase-cloud-messaging google-cloud-functions


    【解决方案1】:

    很可能,您在 firebase api 上调用的某些函数应该是 awaited,但不是。我不熟悉 firebase,无法准确告诉您它是哪一个,但似乎对 firebase API 的任何调用都可能是 awaitable。

    这就是确保您已为 firebase 安装类型定义并使用良好的编辑器的地方。查看您的所有 firebase 调用,并确保它们都没有秘密返回承诺。

    此外,您应该确保您的所有函数和变量都是尽可能强类型的,因为这将帮助您避免任何问题。

    所以,以下几行在我看来很可疑:

    fs.doc(`member/${memberID}`);
    
    transaction.update(docRef, {badgeCount: ++count});
    
    const doc = admin.firestore().doc(`member/${memberID}`);
    

    【讨论】:

      【解决方案2】:

      这是因为您打开了太多的 http 连接来发送推送通知,理想情况下您应该创建 5,10 .. 的批次来发送推送。

      尝试改变,

      return await Promise.all(ids.map(async (id) => { ... });
      

      到,

      while(ids.length) {
          var batch = ids.splice(0, ids.length >= 5 ? 5 : ids.length);
          await Promise.all(batch.map( async (id) => { ... });
      }
      

      【讨论】:

        猜你喜欢
        • 2016-08-22
        • 1970-01-01
        • 2016-06-08
        • 2017-05-10
        • 2015-03-16
        • 1970-01-01
        • 2016-02-26
        • 2017-07-13
        • 1970-01-01
        相关资源
        最近更新 更多