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: '通知已发送' }); }); }); })
关键修正点
- 解析JSON字符串:用
JSON.parse()把数据库中存储的字符串转为web-push需要的JS对象 - 处理数组结果:循环遍历查询返回的每条订阅记录,逐个发送通知
- 错误捕获:添加多层面的错误处理,避免单个操作失败导致整个请求崩溃,同时确保数据库连接被释放
- 异步处理:对
sendNotification使用await保证发送逻辑完成,避免回调嵌套问题
内容的提问来源于stack exchange,提问作者Moha
相关产品推荐
相关产品推荐

