构建一个即时消息应用(九):Conversation 页面
创始人
2024-03-02 05:59:04
0

本文是该系列的第九篇,也是最后一篇。

在这篇文章中,我们将对 对话 conversation 页面进行编码。此页面是两个用户之间的聊天室。在顶部我们将显示其他参与者的信息,下面接着的是最新消息列表,以及底部的消息表单。

聊天标题

让我们从创建 static/pages/conversation-page.js 文件开始,它包含以下内容:

import http from '../http.js'
import { navigate } from '../router.js'
import { avatar, escapeHTML } from '../shared.js'

export default async function conversationPage(conversationID) {
    let conversation
    try {
        conversation = await getConversation(conversationID)
    } catch (err) {
        alert(err.message)
        navigate('/', true)
        return
    }

    const template = document.createElement('template')
    template.innerHTML = `
 
← Back ${avatar(conversation.otherParticipant)} ${conversation.otherParticipant.username}
` const page = template.content return page } function getConversation(id) { return http.get('/api/conversations/' + id) }

此页面接收路由从 URL 中提取的会话 ID。

首先,它向 /api/ conversations/{conversationID} 发起一个 GET 请求,以获取有关对话的信息。 如果出现错误,我们会将其显示,并重定向回 /。然后我们呈现有关其他参与者的信息。

对话列表

我们也会获取最新的消息并显示它们。

let conversation, messages
try {
    [conversation, messages] = await Promise.all([
        getConversation(conversationID),
        getMessages(conversationID),
    ])
}

更新 conversationPage() 函数以获取消息。我们使用 Promise.all() 同时执行这两个请求。

function getMessages(conversationID) {
    return http.get(`/api/conversations/${conversationID}/messages`)
}

发起对 /api/conversations/{conversationID}/messages 的 GET 请求可以获取对话中的最新消息。

    现在,将该列表添加到标记中。

    const messagesOList = page.getElementById('messages')
    for (const message of messages.reverse()) {
        messagesOList.appendChild(renderMessage(message))
    }
    

    这样我们就可以将消息附加到列表中了。我们以时间倒序来显示它们。

    function renderMessage(message) {
        const messageContent = escapeHTML(message.content)
        const messageDate = new Date(message.createdAt).toLocaleString()
    
        const li = document.createElement('li')
        if (message.mine) {
            li.classList.add('owned')
        }
        li.innerHTML = `
     

    ${messageContent}

    ` return li }

    每个消息条目显示消息内容本身及其时间戳。使用 .mine,我们可以将不同的 css 类附加到条目,这样您就可以将消息显示在右侧。

    消息表单

    将该表单添加到当前标记中。

    page.getElementById('message-form').onsubmit = messageSubmitter(conversationID)
    

    将事件监听器附加到 “submit” 事件。

    function messageSubmitter(conversationID) {
        return async ev => {
            ev.preventDefault()
    
            const form = ev.currentTarget
            const input = form.querySelector('input')
            const submitButton = form.querySelector('button')
    
            input.disabled = true
            submitButton.disabled = true
    
            try {
                const message = await createMessage(input.value, conversationID)
                input.value = ''
                const messagesOList = document.getElementById('messages')
                if (messagesOList === null) {
                    return
                }
    
                messagesOList.appendChild(renderMessage(message))
            } catch (err) {
                if (err.statusCode === 422) {
                    input.setCustomValidity(err.body.errors.content)
                } else {
                    alert(err.message)
                }
            } finally {
                input.disabled = false
                submitButton.disabled = false
    
                setTimeout(() => {
                    input.focus()
                }, 0)
            }
        }
    }
    
    function createMessage(content, conversationID) {
        return http.post(`/api/conversations/${conversationID}/messages`, { content })
    }
    

    我们利用 partial application 在 “submit” 事件处理程序中获取对话 ID。它 从输入中获取消息内容,并用它对 /api/conversations/{conversationID}/messages 发出 POST 请求。 然后将新创建的消息添加到列表中。

    消息订阅

    为了实现实时,我们还将订阅此页面中的消息流。

    page.addEventListener('disconnect', subscribeToMessages(messageArriver(conversationID)))
    

    将该行添加到 conversationPage() 函数中。

    function subscribeToMessages(cb) {
        return http.subscribe('/api/messages', cb)
    }
    
    function messageArriver(conversationID) {
        return message => {
            if (message.conversationID !== conversationID) {
                return
            }
    
            const messagesOList = document.getElementById('messages')
            if (messagesOList === null) {
                return
    
            }
            messagesOList.appendChild(renderMessage(message))
            readMessages(message.conversationID)
        }
    }
    
    function readMessages(conversationID) {
        return http.post(`/api/conversations/${conversationID}/read\_messages`)
    }
    

    在这里我们仍然使用这个应用的部分来获取会话 ID。 当新消息到达时,我们首先检查它是否来自此对话。如果是,我们会将消息条目预先添加到列表中,并向 /api/conversations/{conversationID}/read_messages 发起 POST 一个请求,以更新参与者上次阅读消息的时间。


    本系列到此结束。 消息应用现在可以运行了。


    via: https://nicolasparada.netlify.com/posts/go-messenger-conversation-page/

    作者:Nicolás Parada 选题:lujun9972 译者:gxlct008 校对:wxy

    本文由 LCTT 原创编译,Linux中国 荣誉推出

    相关内容

    硬核观察 #353 X.o...
    X.org “大眼睛” 11 年来发布第一个小版本X.Org/X1...
    2024-03-02 08:11:09
    构建一个即时消息应用(九)...
    本文是该系列的第九篇,也是最后一篇。第一篇: 模式第二篇: OAu...
    2024-03-02 05:59:04
    构建一个即时消息应用(八)...
    本文是该系列的第八篇。第一篇: 模式第二篇: OAuth第三篇: ...
    2024-03-02 05:58:13
    构建一个即时消息应用(七)...
    本文是该系列的第七篇。第一篇: 模式第二篇: OAuth第三篇: ...
    2024-03-02 05:56:54
    构建一个即时消息应用(四)...
    本文是该系列的第四篇。第一篇: 模式第二篇: OAuth第三篇: ...
    2024-03-02 05:55:36
    构建一个即时消息应用(六)...
    本文是该系列的第六篇。第一篇: 模式第二篇: OAuth第三篇: ...
    2024-03-02 05:55:24

    热门资讯

    “Linux 中国” 开源社区... 这是一个艰难的决定 —— 这不是调侃,而是当你真正做出改变了你十几年生活轨迹的决定时,你就会明白这个...
    硬核观察 #1263 德国铁路... #1 德国铁路公司招聘 Windows for Workgroups 3.11 管理员该职位要求了解...
    人工智能教程(七):Sciki... 在本系列的 上一篇文章 中,我们用 TensorFlow 构建了第一个神经网络,然后还通过 Kera...
    关闭 WSL 中正在运行的 L... 以下是使用 WSL 关闭在 Windows 内运行的 Linux 系统的不同方法。你使用 WSL 在...
    MX Linux 23.2 “... 最新的 MX Linux 23.2 小版本更新带来了基本的改进和新增功能。MX Linux 推出了 ...
    硬核观察 #1262 网络上最... #1 网络上最古老的软件存档库之一即将关闭美国新墨西哥州立大学(NMSU)最近宣布,即将于 2024...
    如何在 RHEL 上通过绑定配... 在 Linux 中,你可以根据自己的需要创建高级网络设置,如 网络绑定 Network Bondin...
    Linux Matrix 消息... Matrix 用户可以升级 Fractal 6 了!Fractal 是目前 最好的 Matrix 客...
    如何通过 VLC 使用字幕 使用 VLC 媒体播放器播放和管理字幕的新手指南。我是一个超级动漫迷,如果你想观看最新的剧集,那么你...
    硬核观察 #1261 X 计划... #1 X 计划在奥斯汀建立内容审核总部据报道,该部门将招聘 100 名全职员工,将主要关注 CSE ...