-1

I'm using node.js as a backend server for sending push notification from the Firebase Cloud Messaging service. The notifications are working fine with local server but on live server, I get this error:

Error while making request: socket hang up. Error code: ECONNRESET

Things to consider are that...

  • Number of users are in the thousands on live server
  • Firebase version is firebase-admin@6.5.1
  • Previously unregistered tokens are still there. But now registered tokens are being stored.

This is my code for sending notifications:

for (let c = 0; c < tokens.length; c++) 
{
    let notifyTo = tokens[c];
    const platform = platforms[c];

    let payload;
    if (platform === "ios") {
        payload = {
            notification: {
                title: "title",
                subtitle :"messgae",
                sound: "default",
                badge: "1"
            },
            data: {
                sendFrom: "",
                notificationType: "",
                flag: "true"
            }
        };
    } else if (platform === "android") {
        payload = {
            data: {
                title: "",
                message : "",
                flag: "true"
            }
        };
    }

    const registrationtoken = notifyTo;

    await admin.messaging().sendToDevice(registrationtoken, payload)
        .then(function (response) {
            console.log("Successfully sent message:");
        })
        .catch(function (error) {
            console.log("Error sending message: ");
        });
}
4

1 回答 1

2

您的问题是由于您的函数响应客户端的时间过长(超过 60 秒),并且是由以下行引起的:

await admin.messaging().sendToDevice(registrationtoken, payload)

因为您正在等待每个sendToDevice()单独的调用,所以您正在以同步顺序运行您的 for 循环,而不是异步并行运行。

为避免这种情况,您需要使用数组映射,Promise.all()这将允许您构建sendToDevice()请求队列。与您当前的代码一样,任何失败的消息都将被忽略,但我们也会对其进行计数。

您当前的代码使用两个数组,tokens并且platforms,因此在下面的代码中,我使用了一个回调,Array.prototype.map()它接受两个参数 - 当前映射值(来自tokens)和它的索引(您的 for 循环的c值)。然后使用该索引来获取正确的平台条目。

let fcmPromisesArray = tokens.map((token, idx) => {
    let platform = platforms[idx];

    if (platform === "ios") {
        payload = {
            notification: {
                title: "title",
                subtitle :"messgae",
                sound: "default",
                badge: "1"
            },
            data: {
                sendFrom: "",
                notificationType: "",
                flag: "true"
            }
        };
    } else if (platform === "android") {
        payload = {
            data: {
                title: "",
                message : "",
                flag: "true"
            }
        };
    }

    return admin.messaging().sendToDevice(token, payload) // note: 'await' was changed to 'return' here
        .then(function (response) {
          return true; // success
        })
        .catch(function (error) {
            console.log("Error sending message to ", token);
            return false; // failed
        });
});

let results = await Promise.all(fcmPromisesArray); // wait here for all sendToDevice() requests to finish or fail
let successCount = results.reduce((acc, v) => v ? acc + 1 : acc, 0); // this minified line just counts the number of successful results

console.log(`Successfully sent messages to ${successCount}/${results.length} devices.`);

运行此代码段后,不要忘记使用res.send(...)或类似方法将结果发送回客户端。

于 2019-12-08T11:28:52.600 回答