JavaScript方法无法返回数组:FCM消息加载传递失败求助
问题分析与解决
你的问题核心在于**onSnapshot是异步操作**,当前代码会在Firestore返回数据、填充数组之前就执行return chat_messages_arr,所以返回的是空数组(加上调用端的拼写错误,最终显示undefined)。另外调用代码里还有两处明显错误:
先修正调用端的低级错误
你的调用代码里:
var loadmessages = new loadMessagess(chat_thread);
- 函数名拼写错误:
loadMessagess多了一个s,应该是loadMessages - 不该用
new关键字:loadMessages是普通函数,不是构造函数,直接调用即可
修正后的基础调用代码:
function loadMessageses(chat_thread) { loadMessages(chat_thread).then(messages => { console.log(messages); }); }
异步逻辑的正确处理方式
因为onSnapshot是异步监听Firestore数据变化的方法,不能同步返回结果,你需要用Promise或者回调函数来处理异步数据:
方案1:用Promise返回首次加载的消息数组
如果只需要一次性加载历史消息,用getDocs替代onSnapshot更高效,修改loadMessages函数返回Promise:
window.loadMessages = function(newthread = '') { var chatthread = newthread; var chat_messages_arr = []; const recentMessagesQuery = query(collection(getFirestore(), chatthread), orderBy('timestamp', 'asc'), limit(12)); return new Promise((resolve) => { getDocs(recentMessagesQuery).then(snapshot => { snapshot.docChanges().forEach(change => { if (change.type !== 'removed') { var message = change.doc.data(); var chatArr = { // 修正变量名拼写错误:cahtArr → chatArr id: change.doc.id, name: message.name, message: message.text, timestamp: message.timestamp }; chat_messages_arr.push(chatArr); } }); resolve(chat_messages_arr); }); }); };
如果需要实时监听消息变化(后续新增/删除/修改消息都要同步更新数组),可以让函数返回Promise的同时,暴露更新回调:
window.loadMessages = function(newthread = '', onUpdate) { var chatthread = newthread; var chat_messages_arr = []; const recentMessagesQuery = query(collection(getFirestore(), chatthread), orderBy('timestamp', 'asc'), limit(12)); return new Promise((resolve) => { onSnapshot(recentMessagesQuery, snapshot => { snapshot.docChanges().forEach(change => { if (change.type === 'removed') { // 处理消息删除:从数组移除对应项 chat_messages_arr = chat_messages_arr.filter(item => item.id !== change.doc.id); } else { var message = change.doc.data(); var chatArr = { id: change.doc.id, name: message.name, message: message.text, timestamp: message.timestamp }; // 处理消息修改:先移除旧项再添加新项 if (change.type === 'modified') { chat_messages_arr = chat_messages_arr.filter(item => item.id !== change.doc.id); } chat_messages_arr.push(chatArr); } }); // 首次加载返回初始数组,后续更新触发回调 resolve(chat_messages_arr); if (onUpdate) onUpdate([...chat_messages_arr]); // 传递数组副本避免外部直接修改 }); }); };
对应调用方式(支持实时更新):
function loadMessageses(chat_thread) { loadMessages(chat_thread, (updatedMessages) => { console.log('实时更新的消息:', updatedMessages); }).then(initialMessages => { console.log('首次加载的消息:', initialMessages); }); }
方案2:使用回调函数(传统异步处理方式)
如果不想用Promise,也可以让loadMessages接受一个回调参数,当数据更新时触发:
window.loadMessages = function(newthread = '', callback) { var chatthread = newthread; var chat_messages_arr = []; const recentMessagesQuery = query(collection(getFirestore(), chatthread), orderBy('timestamp', 'asc'), limit(12)); onSnapshot(recentMessagesQuery, snapshot => { snapshot.docChanges().forEach(change => { if (change.type === 'removed') { chat_messages_arr = chat_messages_arr.filter(item => item.id !== change.doc.id); } else { var message = change.doc.data(); var chatArr = { id: change.doc.id, name: message.name, message: message.text, timestamp: message.timestamp }; if (change.type === 'modified') { chat_messages_arr = chat_messages_arr.filter(item => item.id !== change.doc.id); } chat_messages_arr.push(chatArr); } }); callback([...chat_messages_arr]); }); };
调用方式:
function loadMessageses(chat_thread) { loadMessages(chat_thread, (messages) => { console.log(messages); }); }
关键总结
- 异步操作不能同步返回结果,必须用Promise或回调处理
- 注意变量名、函数名的拼写错误,避免低级bug
- 一次性加载用
getDocs,实时监听用onSnapshot并处理各类数据变更
内容的提问来源于stack exchange,提问作者DevOops
相关产品推荐
相关产品推荐

