ExpoPushTicket 不包含相应的 PushToken,以防出现错误,如何知道哪个 PushToken 导致错误并将其从数据库中删除

Abi*_*Ali 7 push-notification node.js firebase react-native expo

我正在尝试向我的应用程序的多个用户发送推送通知(发送多个用户很常见。例如,通知所有用户一项新功能)。

发送通知时,ExpoPushTicket数组包含错误,例如DeviceNotRegistered,我想pushToken从数据库中删除这些错误,因为它表明用户已卸载该应用程序。

但问题是我无法区分工作令牌和非工作令牌,因为请求中有超过 1 个令牌,而响应中有超过 1 个ExpoPushTicket对象。

我如何正确映射并知道哪些推送令牌产生错误DeviceNotRegistered

这是示例代码和示例响应。

import { Expo, ExpoPushMessage, ExpoPushTicket } from "expo-server-sdk";

const sendNotifications = async (): Promise<ExpoPushTicket[]> => {
  const expo = new Expo();
  // 100 push tokens for example.
  const notifications: ExpoPushMessage[] = [
    {
      to: '<EXPO_PUSHTOKEN1>',
      title: 'New Feature',
      body: 'We have a fantastic new feature, you might be interested to checkout.',
    },
    {
      to: '<EXPO_PUSHTOKEN2>',
      title: 'New Feature',
      body: 'We have a fantastic new feature, you might be interested to checkout.',
    }
  ];
  const filteredNotifications = notifications.filter((noti) => Expo.isExpoPushToken(noti.to));
  
  const chunks = expo.chunkPushNotifications(filteredNotifications);
  const promises = [];
  chunks.forEach((chunk) => {
    promises.push(expo.sendPushNotificationsAsync(chunk));
  });
  
  const chunkTickets = await Promise.all(promises);
  console.log("chunk tickets", chunkTickets);
  
  // Chunk Tickets does not contain the corresponding pushToken in case of success/error,
  // so I am unable to know in case of error, which pushToken should be removed from database.
  // I tried to get the receipts
  
  const ticketIds = [];
  chunkTickets?.forEach((chunk) => {
    chunk?.forEach((ticket) => {
      if ( ticket.id ) {
        ticketIds.push(ticket.id);
      }
    });
  });
  
  const receipts = await expo.getPushNotificationReceiptsAsync(ticketIds);
  console.log("receipts", receipts);
  
  // But unfortunately, receipts are also not having the "pushToken" field
  // So I don't know which pushToken is causing error and should be removed from database
  
  return receipts;
};
Run Code Online (Sandbox Code Playgroud)

响应示例:

// Sample Response
const chunkTickets = [
  [
    {
      "id": "d4574aeb-6e68-474a-9f60-7cba340a7797",
      "status": "error",
      "message": "The recipient device is not registered with FCM.",
      "details": {
        "error": "DeviceNotRegistered",
        "fault": "developer"
      }
    }
  ]
]

const receipts = {
  "d4574aeb-6e68-474a-9f60-7cba340a7797": {
    "status": "error",
    "message": "The recipient device is not registered with FCM.",
    "details": {
      "fault": "developer",
      "error": "DeviceNotRegistered",
      "sentAt": 1645233143
    },
    "__debug": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*ino 2

您的块 const chunks = expo.chunkPushNotifications(filteredNotifications); 中包含推送令牌,它们直接对应于您的 chunkTickets 和收据。

我能够做这样的事情

const tickets = [];
return Promise.all(
    chunks.map((chunk) => expo.sendPushNotificationsAsync(chunk).then((ticketChunkResponse) => {
        tickets.push(_.merge(...ticketChunkResponse, ...chunk));
        return Promise.resolve(true);
      }),
    ),
  ).then((res) => {
     checkReceipts(tickets);
  });
Run Code Online (Sandbox Code Playgroud)

我将这些块与其相应的响应合并,然后使用 lodash 的合并函数将它们发送到我的 checkReceipt 函数

  • 是的,他们可以而且可能应该...一些用户将使用不同的设备,并且应该收到他们使用过的每个设备的推送。 (2认同)