Javascript 使用Mongodb响应本机聊天
我对react native非常陌生,目前正在开发聊天/论坛应用程序。最近,我在尝试为我的应用程序创建直接消息部分时遇到了一些问题。我不知道如何将我的数据库连接到前端。问题是: 我使用一个mongodb数据库,它由两个集合组成:消息和对话 每个会话都有一个唯一的Id,每条消息都有一个对应于它所属的会话的chatId 在我的react原生应用程序中,在一个直接消息组件中,我有一个显示不同聊天记录的Javascript 使用Mongodb响应本机聊天,javascript,mongodb,asynchronous,react-native,chat,Javascript,Mongodb,Asynchronous,React Native,Chat,我对react native非常陌生,目前正在开发聊天/论坛应用程序。最近,我在尝试为我的应用程序创建直接消息部分时遇到了一些问题。我不知道如何将我的数据库连接到前端。问题是: 我使用一个mongodb数据库,它由两个集合组成:消息和对话 每个会话都有一个唯一的Id,每条消息都有一个对应于它所属的会话的chatId 在我的react原生应用程序中,在一个直接消息组件中,我有一个显示不同聊天记录的flatlist 当直接消息组件willMount()调用异步函数getChats(),该函数从当前用
flatlist
当直接消息组件willMount()
调用异步函数getChats()
,该函数从当前用户所属的数据库中获取聊天记录。然后将获取的聊天设置为状态
然后,在getChats()
中,在聊天设置为状态后,我有一个for循环
,它基本上循环了整个this.state.chats
数组,然后调用一个函数getMessages(this.state.chats[I].id)
,该函数获取与聊天id共享相同聊天id的所有消息。然后将获取的消息添加到this.state.messages
最后,一个带有道具的平面列表
keyExtractor={(item)=>item.\u id}
数据={this.state.chats}
renderItem={({item})=>此
extraData={this.state}
,呈现聊天记录
我希望能够在聊天视图中显示最新的消息内容和发件人,但是,有一个错误指出消息内容未定义
我认为这可能是因为消息没有设置为聊天前的状态,但我不确定
你将如何解决这个问题?您要更改前端还是后端?你能把两者都换一下吗?我应该分享我的代码以便更容易理解问题吗
提前谢谢。对问题的解释非常清楚!简言之:
如何使用React Native、MongoDB、NodeJS和Express构建包含对话概述(显示每个对话的最后一条消息)的聊天页面
一些注意事项:
- 使用一致的命名,即将
chatId
重命名为conversationId
,将chats
重命名为conversations
- 尽量减少互联网请求,因为它们是资源密集型的,而且速度很慢
- 现在,您的算法进行
对话。每次打开页面时,count+1
请求可能只是1
- 对于第一页,您只需要每次对话中的最后一条消息
- 打开对话页面时,加载对话的其余消息
- 因此,您不需要
extraData
字段
- (尽管存在缓存,请参见其他注释)
- 例如,使用GraphQL
query('currentUser.conversations{text,messages(limit 1),…}')
- 例如,使用rest+mongoose:
// controller
// see https://stackoverflow.com/questions/32207457/node-js-mongoose-populate-limit
// populate the first item in conversation.messages
const conversations = ()=> db.Conversations
.find(...)
.populate({ path: 'messages', options: { limit: 1, sort: { created: -1} }}))
.exec(...)
// router
router.get('/conversations', ({user}, res)=>
getConversations({user})
.then(data=> res.send({data}))
.catch(error=> res.send({error}))
)
- (这假设消息是会话中的虚拟财产)
- 假设所有数据都已损坏;如果消息数据丢失,应用程序不应该崩溃。在访问属性之前,请检查该属性是否存在,并在继续之前将其转换为预期的数据类型
- 确保错误没有被“吞没”;例如,确保始终有一个
。如果有,请捕获,并记录错误。然后,并将错误消息粘贴到问题上(如果有)
Uncaught TypeError:在执行a.b.c
时,如果您知道a
是一个对象,则无法读取未定义的属性“c”,可以通过首先检查来避免<代码>如果(a.b)使用(a.b.c)
,或使用短路:a.b&&use(a.b.c)
- 正确的假设,发生了什么:
ConversationsPage
已初始化,状态。conversations
为空
willMount
调用->fetchAllConversations
已启动,需要时间,异步
willMount
ends->render
called->empty list rendered
fetchAllConversations
'第一个请求完成->setState{conversations}
->render
再次调用->呈现完整列表(在您的情况下,它崩溃是因为缺少最后一个消息字段)
fetchAllConversations
调用fetchMessagesForConversations
,这会发出许多api请求,并可能多次调用setState
,从而导致重新呈现
- 不要忘记加载状态
state = {loading: false}
render () {
const {loading} = this.state
return <FlatList renderHeader={()=> loading? <ActivityIndicator .../>: null} .../>
}
- 这将使流量减少到:
ConversationsPage
已初始化,状态。conversations
为空
willMount
调用->reload
已启动,需要时间,异步
willMount
ends->render
called->loading indicator rendered
重新加载
的唯一请求完成->设置状态{conversations}
->再次调用渲染
->渲染的完整列表
补充说明:
- 查看
docker
以简化服务器设置(即让mongodb+NodeJ一起运行)
- 我假设您已经有了一个中间件来进行身份验证,并在查询中添加了正确的授权逻辑(例如,仅查找授权用户应有权访问的对话/消息)
- ie.
db.Conversation.find({参与者:{$includes:req.user.\u id}})//伪代码
- 例如,在消息中,首先查看具有该id的对话是否有用户作为参与者
- 如何处理分页?(例如,为了防止数据传输速度慢
state = {loading: false}
render () {
const {loading} = this.state
return <FlatList renderHeader={()=> loading? <ActivityIndicator .../>: null} .../>
}
async fetchAllConversations () {
const conversations = await api.conversations()
await Promise.all(conversations.map(c=> c.messages = await api.messagesForConversationId(c._id)))
// similar to for (let i=0; i<conversations.length; i++) {
// const c = conversations[i]; c.messages = await api.messagesForConversationId(c._id)}
return conversations
}
async reload () {
this.setState({loading: true})
this.fetchAllConversations()
.then(conversations=> this.setState({conversations}))
.catch(showError)
// stop loading both on error and success
.then(()=> this.setState({loading: false}))
}
state = {loading: false, conversations: []}
willMount () { this.reload() }
async fetchAllConversationsIncludingLastMessage () {
const conversations = await api.conversationsWithLastMessage()
return conversations
}