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接口会拒绝你的请求。
附上你提供的问题截图:

内容的提问来源于stack exchange,提问作者rituparna
相关产品推荐
相关产品推荐

