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

如何将前端变量传递至Service Worker?及JSON解析错误排查

问题分析与解决方案

前端Service Worker问题

1. Fetch请求格式错误(SyntaxError的直接诱因)

你在saveSubscription函数中设置了Content-Type: application/json,但body直接传入了对象——浏览器不会自动将对象转为JSON字符串,后端bodyParser.json()解析时会收到非JSON格式的内容,从而抛出SyntaxError: Unexpected token o in JSON at position 1。

修复代码:

// service.js(Service Worker文件)
const saveSubscription = async (subscription, usrCode) => { 
  const SERVER_URL = 'https://mywebsite:4000/save-subscription' 
  const subscriptionStr = JSON.stringify(subscription);
  console.log(subscriptionStr);
  console.log(usrCode);
  const response = await fetch(SERVER_URL, {
    method: 'post', 
    headers: { 
      'Content-Type' : 'application/json', 
    }, 
    // 必须用JSON.stringify将body转为JSON字符串
    body : JSON.stringify({
      subscription: subscriptionStr,
      usrCode: usrCode
    }) 
  }) 
  return response
}

2. usrCode在Service Worker中输出undefined的问题

Service Worker运行在独立线程,无法直接访问主线程变量,你需要通过主线程向它传递usrCode:

主线程传递usrCode示例:

// 页面主线程JS文件
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/service.js')
    .then(async (registration) => {
      const subscription = await registration.pushManager.subscribe(/* 你的订阅配置 */);
      const usrCode = '用户标识ID'; // 这里是你已获取到的正确usrCode
      // 向Service Worker发送消息传递参数
      registration.active.postMessage({ type: 'SAVE_SUBSCRIPTION', subscription, usrCode });
    });
}

Service Worker接收处理:

// service.js中添加消息监听
self.addEventListener('message', async (event) => {
  if (event.data.type === 'SAVE_SUBSCRIPTION') {
    const { subscription, usrCode } = event.data;
    await saveSubscription(subscription, usrCode);
  }
});

// 保留修复后的saveSubscription函数
const saveSubscription = async (subscription, usrCode) => { 
  // ... 上述修复后的代码 ...
}

后端Node.js/Express问题

1. 函数调用参数错误

你调用saveToDatabase时,错误地将usrCode作为JSON.stringify的第二个参数传入,导致saveToDatabase的第二个参数usrCode为undefined,同时重复序列化了subscription(前端已完成字符串转换)。

修复代码:

// index.js(后端文件)
app.post('/save-subscription', async (req, res) => {
  const usrCode = req.body.usrCode;
  const subscription = req.body.subscription;
  // 直接传递两个独立参数,无需再次JSON.stringify
  await saveToDatabase(subscription, usrCode);
  res.json({ message: 'success' });
})

2. 异步函数未正确封装

saveToDatabase标记为async,但内部使用回调形式的pool.getConnection,await无法等待回调完成,会导致请求提前返回且错误无法捕获。需要将回调转为Promise:

修复后的saveToDatabase:

const saveToDatabase = async (subscription, usrCode) => {
  return new Promise((resolve, reject) => {
    pool.getConnection(function (err, connection) {
      if (err) {
        reject(err);
        return;
      }
      console.log(usrCode);
      console.log(subscription);
      // 使用参数化查询规避SQL注入风险
      const sql = 'INSERT INTO webpushsub (webpushsub_info, webpushsub_code) VALUES (?, ?)';
      connection.query(sql, [subscription, usrCode], function (err, result, fields) {
        connection.release();
        if (err) {
          reject(err);
          return;
        }
        console.log(result);
        resolve(result);
      });
    });
  });
}

3. 规避SQL注入风险

原代码直接将变量拼接进SQL语句,存在严重安全隐患,必须使用参数化查询(上述代码已修正)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 20:55:10