You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js+Express+MySQL下web-push发送通知查询订阅报错排查

问题:webpush.sendNotification 报错 "You must pass in a subscription with at least an endpoint"

我是Node.js和Service Workers的新手,正在为网站添加推送通知功能,后端采用Express框架与MySQL数据库。按照教程操作时,订阅数据可正常存入数据库,但测试发送通知执行SELECT查询后,调用webpush.sendNotification时出现错误:

C:\...\web-push-lib.js:87
      throw new Error('You must pass in a subscription with at least '
            ^

Error: You must pass in a subscription with at least an endpoint.

问题出在以下代码段:

//route to test send notification
app.get('/send-notification', (req, res) => {
    //connect to the pool
    pool.getConnection(function (err, connection) {
        if (err) throw err; // not connected!
        const sub = { subscription: null };
        connection.query(`SELECT webpushsub_info FROM webpushsub`, function (err, result, fields) {
          // if any error while executing above query, throw error
          if (err) throw err;
          // if there is no error, you have the result
          sub.subscription = result;
          const message = 'Inscription done';
          webpush.sendNotification(sub.subscription, message)
          connection.release();
          res.json({ message: 'message sent' });
    });
  });
})

编辑补充:
打印查询结果得到如下内容:

RowDataPacket {
   webpushsub_info: '{ //that's the column name where I store subscriptions
      "endpoint":"https://fcm.googleapis.com/fcm/send/some_endpoint",
      "expirationTime":null,
      "keys":{
          "p256dh":"some key",
          "auth":"an other key"
       }
   }',
...
}

打印单个元素result[0].webpushsub_info,得到的是与数据库中一致的内容。根据web-push的npm文档说明,其期望的格式是浏览器中PushSubscription经JSON.stringify后的输出。


解决方案

问题根源

  • 查询返回的result是包含多条记录的数组,直接传给sendNotification不符合参数要求
  • 数据库中存储的webpushsub_info是JSON字符串,未解析为JS对象,web-push无法识别其中的endpoint字段

修正后的代码

//route to test send notification
app.get('/send-notification', (req, res) => {
    pool.getConnection(function (err, connection) {
        if (err) {
            console.error(err);
            return res.status(500).json({ error: '数据库连接失败' });
        }
        connection.query(`SELECT webpushsub_info FROM webpushsub`, function (err, result, fields) {
            if (err) {
                console.error(err);
                connection.release();
                return res.status(500).json({ error: '查询订阅数据失败' });
            }
            // 循环处理每个订阅记录
            result.forEach(async (row) => {
                try {
                    // 将JSON字符串解析为JS对象
                    const subscription = JSON.parse(row.webpushsub_info);
                    const message = 'Inscription done';
                    await webpush.sendNotification(subscription, message);
                } catch (notifyErr) {
                    console.error('发送通知失败:', notifyErr);
                }
            });
            connection.release();
            res.json({ message: '通知已发送' });
        });
    });
})

关键修正点

  1. 解析JSON字符串:用JSON.parse()把数据库中存储的字符串转为web-push需要的JS对象
  2. 处理数组结果:循环遍历查询返回的每条订阅记录,逐个发送通知
  3. 错误捕获:添加多层面的错误处理,避免单个操作失败导致整个请求崩溃,同时确保数据库连接被释放
  4. 异步处理:对sendNotification使用await保证发送逻辑完成,避免回调嵌套问题

内容的提问来源于stack exchange,提问作者Moha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:40:24