这两天的工作中,我重构了一个项目里的客服聊天功能,是小程序的,用了小程序提供的websocket有关的接口,我感觉很简单,和web端的接口大体一致,不过我喜欢封装后去使用,封装成一个类,创建一个类的实例,通过这个实例上的方法去调用方法,去监听返回的消息,同时发送消息,我觉得这样会比较方便。
/**
* 返回一个布尔值判断传入的url是否为WSS开头的链接
* @param {String} url 需要判断的URL
*/
function isAbsoluteWss(url) {
return /^(wss:\/\/).*/.test(url)
}
export default class Socket {
/** 链接的URL */
url = ''
/** 是否链接成功的状态 */
socketOpenStatus = false
/** 实例 */
websocket = null
/** 消息队列 */
socketMsgQueue = []
/** 消息监听的函数 */
fn = null
/**
*
* @param {String} url websocket的链接地址
* @param {Function} fn 消息监听事件
*/
constructor(url, fn) {
if (!url)
throw new Error('websocket的链接URL不能为空')
if (!isAbsoluteWss(url))
throw new Error(`websocket的链接${url}必须是以 wss:// 开头`)
this.url = url
this.fn = fn
}
/** 链接websocket */
connect() {
this.websocket = wx.connectSocket({
url: this.url
})
// 监听websocket链接打开
this.websocket.onOpen((data) => {
this.socketOpenStatus = true
// 初始化监听事件
this.initHandleMonitor()
if (this.fn) {
this.fn({
type: 'open',
data
})
}
// 如果消息队列里有消息
if (this.socketMsgQueue.length) {
this.socketMsgQueue.forEach(item => item())
}
this.socketMsgQueue = []
})
}
/** 发送消息 */
send(data) {
if (data !== null && typeof data === 'object') {
data = JSON.stringify(data)
}
// 判断当前的链接是否链接成功
if (this.socketOpenStatus) {
this.websocket.send({
data
})
} else {
this.socketMsgQueue.push(() => {
this.websocket.send({
data
})
})
}
}
/** 监听消息的绑定 */
initHandleMonitor() {
/** 消息的回调 */
this.websocket.onMessage(res => {
const data = JSON.parse(res.data)
if (this.fn) {
this.fn({
type: 'message',
data
})
}
})
/** 报错的回调 */
this.websocket.onError(res => {
this.socketOpenStatus = false
if (this.fn) {
this.fn({
type: 'error',
data: res.errMsg
})
}
})
/** 关闭的回调 */
this.websocket.onClose(data => {
this.socketOpenStatus = false
if (this.fn) {
this.fn({
type: 'close',
data
})
}
})
}
/** 关闭websocket链接 */
close(code, reason) {
if (this.socketOpenStatus) {
this.socketOpenStatus = false
this.websocket.close({
code,
reason
})
}
}
/** 返回是否链接成功 */
isOpen() {
return this.socketOpenStatus
}
}
HTTP无法轻松实现实时应用:HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。我们可以非常轻松的捕获浏览器上发生的事件(比如用户点击了盒子)
Nginx 转发 socket 端口常见场景:在线学习应用,在常规功能之外,增加一个聊天室功能,后端选择 swoole 提供服务提供者,同时不想前端直接 ip:port 方式链接到服务,需要使用 Nginx 进行转发。
服务器端:使用express服务;简单的使用websocket.io;使用命名空间 实例中两个命名空间info job;客户端 vue为例引入socket.io-client
Socket 的中文翻译过来就是“套接字”。套接字是什么,我们先来看看它的英文含义:插座。Socket 就像一个电话插座,负责连通两端的电话,进行点对点通信,让电话可以进行通信,端口就像插座上的孔,端口不能同时被其他进程占用。而我们建立连接就像把插头插在这个插座上
Socket.IO是一个WebSocket库,可以在浏览器和服务器之间实现实时,双向和基于事件的通信。它包括:Node.js服务器库、浏览器的Javascript客户端库。它会自动根据浏览器从WebSocket、AJAX长轮询、
轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接;长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接
await 后面若是跟的Promise,则接受Promise resolve的值。Promise reject的值需要try...catch住,或者await 后面的表达式跟着.catch()
传统的客户端和服务器通信协议是HTTP:客户端发起请求,服务端进行响应,服务端从不主动勾搭客户端。这种模式有个明显软肋,就是同步状态。而实际应用中有大量需要客户端和服务器实时同步状态的场景
最近在一个 React 项目中,使用到了 socket.io 处理即时消息,这里面有几点容易被忽视的问题,例如:在 React 单页面应用中如何防止出现多个 socket 实例、在任意的的组件内如何方便的取到 socket 实例
Socket.IO 不仅支持 WebSocket,还支持许多种轮询机制以及其他实时通信方式,并封装了通用的接口。这些方式包含 Adobe Flash Socket、Ajax 长轮询、Ajax multipart streaming 、持久 Iframe、JSONP 轮询等
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!