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

Firestore保存数据时notification_key字段出现undefined问题求助

解决Firestore写入时notification_key为undefined的问题

嘿,我一眼就看出你遇到的问题了——这是JavaScript异步操作执行顺序导致的典型坑!

问题根源

你用的request()是异步函数,它不会阻塞后续代码的执行。当你执行到var data = {... notification_key: tokenName ...}这行时,request的回调函数还没跑完(也就是GCM接口的响应还没回来),这时候tokenName还没被赋值,自然就是undefined,写入Firestore的时候当然也是undefined了。

看你控制台的日志也能印证这点:tokenName的日志在后面才打印,但写入Firestore的代码早就执行完了。

修复方案

我给你两种修复方式,选你顺手的来:

方案1:把写入逻辑放进回调内部

把所有依赖tokenName的代码(构造data、写入Firestore)都放到request的回调函数里,确保只有拿到notification_key之后才执行写入操作:

exports.saveGroups = functions.firestore.document("Users/{user_id}").onWrite((change,context) => { 
  const token_id1 = change.after.data().token_id; 
  const token_email = change.after.data().email; 
  const image = change.after.data().image; 
  const name1 = change.after.data().name; 
  const key = change.after.data().notification_key; 
  const user_id = context.params.user_id; 

  console.log('token_id is: ' + token_id1); 
  console.log('token_email is:' + token_email); 
  console.log('user_id is:' + user_id); 

  if (key === undefined) { 
    console.log('key was not present, hence create'); 
    var options = { 
      url: 'https://android.googleapis.com/gcm/notification', 
      method: 'POST', 
      headers: headers, 
      json: {
        'operation': 'create', 
        'notification_key_name': token_email, 
        'registration_ids': [token_id1]
      } 
    };

    // 把写入逻辑移到回调里,确保tokenName已赋值
    request(options,function (error, response, body) { 
      if (error) {
        console.error('请求GCM接口出错:', error);
        return;
      }
      const tokenName = body.notification_key; 
      console.log('获取到的notification_key:', tokenName); 

      var data = { 
        image: image, 
        email: token_email, 
        name: name1, 
        notification_key: tokenName, 
        token_id: token_id1, 
        extra: 'created' 
      }; 

      console.log('准备写入Firestore的数据:', data); 

      // 返回Promise,避免Cloud Functions提前终止
      return db.collection('Users').doc(user_id).set(data)
        .then(() => console.log('数据写入成功'))
        .catch(err => console.error('写入Firestore失败:', err));
    }); 
  } else {
    console.log('key is present , do not create but add'); 
    return Promise.resolve(); // 必须返回Promise,确保函数正常结束
  }
});

方案2:用async/await简化异步逻辑

如果你觉得回调嵌套看着麻烦,可以用request-promise(需要先安装:npm install request-promise)把请求转换成Promise,然后用async/await让代码更像同步逻辑:

const rp = require('request-promise');

exports.saveGroups = functions.firestore.document("Users/{user_id}").onWrite(async (change,context) => { 
  const token_id1 = change.after.data().token_id; 
  const token_email = change.after.data().email; 
  const image = change.after.data().image; 
  const name1 = change.after.data().name; 
  const key = change.after.data().notification_key; 
  const user_id = context.params.user_id; 

  console.log('token_id is: ' + token_id1); 
  console.log('token_email is:' + token_email); 
  console.log('user_id is:' + user_id); 

  if (key === undefined) { 
    console.log('key was not present, hence create'); 
    var options = { 
      url: 'https://android.googleapis.com/gcm/notification', 
      method: 'POST', 
      headers: headers, 
      json: {
        'operation': 'create', 
        'notification_key_name': token_email, 
        'registration_ids': [token_id1]
      } 
    };

    try {
      // 等待请求完成,拿到响应体
      const body = await rp(options);
      const tokenName = body.notification_key; 
      console.log('获取到的notification_key:', tokenName); 

      var data = { 
        image: image, 
        email: token_email, 
        name: name1, 
        notification_key: tokenName, 
        token_id: token_id1, 
        extra: 'created' 
      }; 

      console.log('准备写入Firestore的数据:', data); 

      // 等待写入完成
      await db.collection('Users').doc(user_id).set(data);
      console.log('数据写入成功');
    } catch (error) {
      console.error('操作失败:', error);
      throw error; // 抛出错误让Cloud Functions捕获并记录
    }
  } else {
    console.log('key is present , do not create but add'); 
  }
});

额外注意事项

  • 错误处理:一定要捕获请求和写入过程中的错误,不然函数可能静默失败,你都不知道哪里出问题。
  • Cloud Functions异步规范:异步函数必须返回Promise或者用async/await,否则Cloud Functions会在异步操作完成前就终止进程,导致操作失败。
  • headers检查:确保你的headers变量包含了正确的Authorization头(比如Authorization: key=你的服务器密钥),不然GCM接口会拒绝你的请求。

附上你提供的问题截图:
Firestore中notification_key显示为undefined
控制台日志中tokenName为undefined

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:57:51