前言
随着跨端技术的发展,前端开发职能不再局限于浏览器,而是具备了很多客户端开发的能力,比如桌面应用框架Electorn,移动App框架React native.
一般而言,前端同学对http协议非常熟悉,在平时的工作中使用http与后端通信居多.但在原生客户端领域,比如Java语言开发的安卓应用,与后端通信的方式大多采用socket.
众所周知,http连接是一种短连接,即客户端向服务器端发送一次请求,服务器端响应后连接即会断掉.而socket连接是一种长连接,理论上客户端和服务器端一旦建立起连接将不会主动断掉.
前端领域存在一个和socket连接功能相似的通信协议,即WebSocket.WebSocket创建了一种持久性的连接,后端不仅能正常处理客户端发送的消息,还能主动向客户端推送消息.
后端主动推送消息的能力在一些特殊的场景中太重要了,比如App接受到的信息通知,即时通讯接受的好友信息,另外面板上实时展现波动的金融数据.
不管是桌面应用框架Electron,还是App开发框架React native,它们都拥有基于原生平台封装的WebSocket.比起浏览器端开放的WebSocket,原生平台提供的支持要稳定很多.
因此在使用前端技术开发客户端应用时,完全可以使用WebSocket协议作为前后端通信的主要方式,不再需要往项目中引入http,因为http拥有的能力WebSocket同样也能找到替代方案.
本文接下来将详细介绍用react hook开发一款客户端应用时,如何在项目中搭建有效的通信机制,让WebSocket和redux有机结合,在不影响前端习惯的编程风格下,建立起客户端与服务器的全双工通信.
实现
数据格式
前后端约定连接建立后,使用WebSocket协议通信的数据格式(参考如下).
{
request_id,
command,
data,
}
request_id是一段随机生成的字符串,用来标识本次客户端向服务器请求的id值.command是命令关键词,类似于接口中的url,后端根据此标识来决定返回接口数据.data是发送的参数.
前端向后端发起请求时,以上3个参数都得携带,其他参数可根据业务需要增添.
后端主动向前端推送消息时,只需要发送command和data参数即可.客户端监听command,根据值的不同进行相应的操作.
在整个项目的通信架构下,前端需要搭建好以下两种通信机制.
-
客户端向服务器发送请求,服务器处理请求并返回响应结果,客户端接受响应结果再做后续处理.这种机制模拟了类似于前端
ajax的通信方式,客户端除了发送请求,还要负责接受该请求的响应. -
服务器主动向客户端推送消息,客户端接受消息.
以上两种机制基本满足了开发的需要,接下来在项目实战中实现以上两种机制(源代码贴在了文章结尾).
登录功能
登录页如下,页面内容很简答,两个输入框,输入账号和密码.还有一个登录按钮.
鼠标点击登录按钮时,dispatch触发LoginAction,此时客户端向服务器发起登录请求,请求成功后进入then的回调函数,打印出登录成功并且路由跳转到首页home.
import { LoginAction } from "../../redux/actions/login";
export default function Login() {
const dispatch = useDispatch();
const history = useHistory();
//省略
...
//登录
const login = ()=>{
dispatch(LoginAction()).then(()=>{
console.log("登录成功!");
history.push("/home");
})
}
return (
<div>
<ul>
<li>登录账号:</li>
<li>
<div><input onChange={updateUser} type="text" placeholder="请输入账号" /></div>
</li>
<li>登录密码:</li>
<li>
<div><input onChange={updatePwd} type="text" placeholder="请输入密码" /></div>
</li>
</ul>
<button onClick={login}>立即登录</button>
</div>
)
}
现在进入LoginAction函数的内部实现,探索它是如何实现发起请求 - 接受响应(代码如下).
LoginAction内部调用了fetch函数,action的type值为"PUSH_MESSAGE".
从这里大概可以推断出fetch内部调用了dispatch,派发了一个type为"PUSH_MESSAGE"的action.
另外fetch函数返回了一个Promise,在then回调函数里接受后端返回的响应.
import { fetch } from "./global";
// 组装action数据类型
const loginType = (username,password)=>{
return {
type:"PUSH_MESSAGE", // 实际开发中这里应该用变量替代
value:{
command:"login",
data:{
username,
password
}
}
}
}

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



