同构Go应用 您所在的位置:网站首页 htmldivelement操作方法 同构Go应用

同构Go应用

2023-04-05 05:15| 来源: 网络整理| 查看: 265

在上一章中,我们考虑了如何通过 web 表单验证和处理用户生成的数据。当用户正确填写联系表时,它成功地通过了两轮验证,并向用户显示了一条确认消息。提交表单后,工作流程即告完成。如果我们想考虑一个更吸引人的工作流,那用户可能会以类似会话的方式参与服务器端应用呢?

今天的网络与蒂姆·伯纳斯·李(Tim Berners Lee)在 20 世纪 90 年代初设计的新生网络大不相同。当时,网络的重点是超链接连接的文档。客户端和服务器之间的 HTTP 事务总是意味着短暂的。

在 21 世纪初,这种情况开始改变。研究人员演示了服务器与客户端保持持久连接的方法。客户端的早期原型是使用 Adobe Flash 创建的,Adobe Flash 是当时唯一可用的技术之一,用于在 web 服务器和 web 客户端之间建立持久连接。

在这些早期尝试的同时,一个效率低下的时代以 AJAX(XHR)长轮询的形式诞生了。客户机将不断地调用服务器(类似于心跳检查),并检查客户机感兴趣的内容的状态是否已更改。服务器将返回相同的疲劳响应,直到客户机感兴趣的状态发生变化,并将其报告回客户机。这种方法的主要低效之处在于必须在 web 客户端和 web 服务器之间进行大量的网络调用。不幸的是,AJAX 长轮询的低效实践变得如此流行,以至于今天许多网站仍然广泛使用它。

实时 web 应用功能背后的思想是通过近实时地提供信息来提供更大的用户体验。请记住,由于网络延迟和物理定律对信号的限制,任何通信都不会在实时中进行,而是在近实时中进行。

实现实时 web 应用功能的主要成分是 WebSocket,这是一种允许 web 服务器和 web 客户端之间双向通信的协议。Go 是实现实时 web 应用的理想编程语言,因为它具有网络和 web 编程的内置功能。

在本章中,我们将构建一个实时聊天应用,演示实时 web 应用功能,这将允许网站用户与基本的聊天机器人对话。当用户向 bot 提问时,bot 将实时响应,用户和 bot 之间的所有通信将通过 web 浏览器和 web 服务器之间的 WebSocket 连接执行。

在本章中,我们将介绍以下主题:

实时聊天功能 实现实时聊天的服务器端功能 实现实时聊天的客户端功能 与代理交谈 实时聊天功能

如今,聊天机器人(也称为代理)为网站用户的需求提供各种各样的服务已经司空见惯,例如,从决定购买什么样的鞋,到提供关于客户投资组合中哪些股票看起来不错的提示。我们将构建一个基本的聊天机器人,它将为 IGWEB 用户提供一些关于同构 Go 的友好提示。

一旦激活实时聊天功能,用户可以继续访问网站的不同部分,而不会中断与机器人的对话,前提是用户使用网站上的导航菜单或在客户端路由的网站上找到的链接。在实际场景中,此功能对于产品销售和技术支持使用场景都是一个有吸引力的建议。例如,如果用户对网站上列出的产品有特定问题,用户可以自由浏览网站,而不必担心失去当前与代理的聊天对话。

请记住,我们将构建的代理具有较低的智能级别。此处介绍的代理仅用于说明目的,生产需要时应使用一种更健壮的人工智能(AI)解决方案。根据您从本章中获得的知识,用一个更健壮的大脑替换当前代理的大脑应该是相当简单的,它将满足您在实时聊天功能中的特定需求。

设计实时聊天室

下图是描述 IGWEB 顶部条的线框设计。在最右边的图标,将激活即时聊天功能点击时:

图 8.1:描绘 IGWEB 顶条的线框设计

下图是描述实时聊天盒的线框设计。聊天盒由名为“Case”的代理的化身图像及其名称和标题组成。聊天室右上角有一个关闭按钮。用户可以在底部文本区域向代理输入他们的消息,该区域具有占位符文本,在此处键入您的消息。与人和机器人的对话将出现在聊天框的中间区域:

图 8.2:实时聊天盒的线框设计

实现实时聊天盒模板

为了让聊天盒出现在网站的所有部分,我们需要将聊天盒div容器放置在网页布局模板(layouts/webpage_layout.tmpl中的主要内容div容器的正下方:

聊天盒将在shared/templates/partials文件夹的chatbox_partial.tmpl源文件中作为部分模板实现:

Chat with X Powered by Isomorphic Go

这是实现在线聊天框的图 8.2中描述的线框设计所需的 HTML 标记。请注意,input文本字段的 id 为"chatboxInputField"。这是input字段,用户可以在该字段中键入他们的消息。创建的每条消息,无论是用户编写的消息还是机器人编写的消息,都将使用livechatmsg_partial.tmpl模板:

每个消息都位于自己的div容器中,该容器有两个div容器(以粗体显示),其中包含消息发送者的名称和消息本身。 live chat 功能中没有必要的按钮,因为我们将添加一个事件侦听器,以侦听是否按下 Enter 键,从而通过 WebSocket 连接将用户的消息提交到服务器。

现在,我们已经实现了用于呈现聊天框的 HTML 标记,让我们检查一下在服务器端实现实时聊天功能所需的功能。

实现实时聊天的服务器端功能

激活实时聊天功能后,我们将在 web 客户端和 web 服务器之间创建一个持久的 WebSocket 连接。Gorilla web Toolkit 在其websocket包中提供了 WebSocket 协议的出色实现,可在中找到 http://github.com/gorilla/websocket 。要获取websocket包,您可以发出以下命令:

$ go get github.com/gorilla/websocket

Gorilla web toolkit 还提供了一个有用的示例 web 聊天应用: https://github.com/gorilla/websocket/tree/master/examples/chat 。

我们将重新利用 Gorilla 的示例 web 聊天应用来实现实时聊天功能,而不是重新发明轮子。网络聊天示例所需的源文件已复制到chat文件夹中。

为了使用 Gorilla 提供的示例聊天应用实现实时聊天功能,我们需要进行三项主要更改:

来自聊天机器人(代理)的回复应该针对特定用户,而不是发送给每个连接的用户 我们需要创建允许聊天机器人将消息发送回用户的功能 我们需要在 Go 中实现聊天应用的前端部分

让我们更详细地考虑这三点中的每一点。

首先,Gorilla 的网络聊天示例是一个免费的聊天室。任何用户都可以进来,键入一条消息,连接到聊天服务器的所有其他用户都可以看到该消息。实时聊天功能的一个主要要求是聊天机器人和人之间的每次对话都应该是独占的。来自代理的答复必须针对特定用户,而不是所有连接的用户。

其次,Gorilla web toolkit 中的示例 web 聊天应用不会向用户发送任何消息。这就是自定义聊天机器人出现的地方。代理将通过已建立的 WebSocket 连接直接与用户通信。

第三,示例 web 聊天应用的前端部分实现为包含内联 CSS 和 JavaScript 的 HTML 文档。正如您可能已经猜到的,我们将在 Go 中实现实时聊天功能的前端部分,代码将驻留在client/chat文件夹中。

现在我们已经建立了我们的行动计划,以大猩猩网络聊天示例为基础来实现实时聊天功能。

我们将创建的修改后的 web 聊天应用包含两种主要类型:Hub和Client。

轮毂类型

聊天中心负责维护客户端连接列表,并指示聊天机器人向相关客户端广播消息。例如,如果 Alice 问了一个问题“什么是同构 Go?,聊天机器人的答案应该是 Alice 而不是 Bob(Bob 可能还没有问过问题)。 *以下是[T0]结构的外观:

type Hub struct { chatbot bot.Bot clients map[*Client]bool broadcastmsg chan *ClientMessage register chan *Client unregister chan *Client }

chatbot是实现Bot接口的聊天机器人(代理)。这是一个大脑,负责回答客户提出的问题。 clients映射用于注册客户端。map中存储的键值对由键、指向Client实例的指针组成,该值由设置为true的布尔值组成,以指示客户端已连接。客户通过broadcastmsg、register和unregister频道与集线器通信。register通道向集线器注册客户端。unregister通道,在集线器中注销客户端。客户端通过broadcastmsg通道发送用户输入的消息,该通道类型为ClientMessage。下面是我们介绍的[T11]结构:

type ClientMessage struct { client *Client message []byte }

为了实现我们之前提出的第一个主要更改,即代理和用户之间对话的排他性,我们使用ClientMessage结构来存储指向Client实例的指针,该Client实例发送用户消息以及用户消息本身(一个byte片段)。

构造函数NewHub接受实现Bot接口的chatbot并返回一个新的Hub实例:

func NewHub(chatbot bot.Bot) *Hub { return &Hub{ chatbot: chatbot, broadcastmsg: make(chan *ClientMessage), register: make(chan *Client), unregister: make(chan *Client), clients: make(map[*Client]bool), } }

我们实现了一个导出的 getter 方法ChatBot,这样就可以从Hub对象访问chatbot:

func (h *Hub) ChatBot() bot.Bot { return h.chatbot }

当我们实现 RESTAPI 端点以将机器人的详细信息(名称、标题和化身图像)发送到客户端时,此操作将非常重要。 SendMessage方法负责向特定客户端广播消息:

func (h *Hub) SendMessage(client *Client, message []byte) { client.send


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有