Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

关于ChatRoom

学习新东西👋#

最近这几天在学习 React,所以这个项目主要目的是给我熟悉 React,我个人是喜欢边学习一样新东西边动手,只有输出才会让我记忆更深刻,其次也会踩到一些光看是不会碰到的坑,加上之前学习 node.js 好像也没有做什么,于是就想到了结合在一块做一个聊天室。✌

因为是第一次做 React,如果觉得有什么需要修改的欢迎提出Issuse,也欢迎你的 star⭐

项目地址:ChatRoom

项目截图:
1.png
2.png
3.png

后端#

后端基于 Node.js + Express + Socket.io + MongoDB
Node.js 操作 MongoDB 以及用 express 写接口之前都有在博客中大致的总结过:
Node.js+express
Node.Js 操作 MongoDB
这次用的新东西就是 Socket.io。

前人的工作👇#

Socket.IO is a library that enables real-time, bidirectional and event-based communication between the browser and the server

即是说 Socket.io 可以实现服务器与客户端之间的一个实时的双向通信。
在连接 Socket.io 的之前还得先知道WebSocket,在 WebSocket 问世之前,在创建拥有双向通信机制的 web 应用程序时,就只能利用 HTTP 轮询的方式,由此产生了 “短轮询” 和 “长轮询”。

短轮询通过客户端定期轮询来询问服务端是否有新的信息产生,缺点也是显而易见,轮询间隔大了则信息不够实时,轮询间隔过小又会消耗过多的流量,增加服务器的负担。
长轮询是对短轮询的优化,需要服务端做相应的修改来支持。但是每次请求还是都要带上 HTTP 请求头部,而且在长轮询的连接结束之后,服务器端积累的新消息要等到下次客户端连接时才能传递。

Websocket 协议就是为了解决长轮询的痛点而诞生的,其基于 TCP 协议,是一种双全工通信技术、复用 HTTP 握手通道。它与 HTTP 协议的唯一关系就是它的握手请求可以作为一个Upgrade request经由 HTTP 服务器解析,且与 HTTP 使用一样的端口。

接着是Socket.io,Socket.io 底层基于engine.io,封装了 WebSocket,其屏蔽了底层细节,让顶层调用非常简单。同时它还支持许多种轮询机制以及其他通信方式,当环境不支持 WebSocket 的时候它能自动选择最佳的方式来实现网络的实时通信。

使用#

引入 io 设置端口后监听 connect 事件:

const server = require('http').Server(app);  
const io = require('socket.io')(server);  

server.listen(3001); //端口设置3001

io.on(('connection', socket=>{
    
    ………………

})

接着通过最重要的两个 api,emiton来发送以及监听事件

  • socket.emit (eventName,[ ...args]):发射(触发)一个事件
  • socket.on (eventName, callback):监听一个 emit 发射的事件
//监听xxx事件,输出传进来的data对象
socket.on('xxx',data=>{
  console.log(data);
})
//发送xxx事件,传出去一个对象,里面有name属性
socket.emit('xxx',{name:'magren'})

另外用到的方法

  • socket.join (id):加入到一个 room 为 id 的房间中
  • socket.broadcast.to (id).emit ( ):广播给 room 为 id 的除了‘我’以外的所有人
  • io.sockets.in (id).emit ( ):广播给 room 为 id 的所有人

前端#

前端基于 React + Redux + Typescript + Antd

向后台发送消息以及监听很简单,只需要引入socket.io-client,接着使用 emit 发送和 on 监听事件即可。

const socket = require('socket.io-client')('ws://localhost:3001',{transports: ['websocket']})

//监听信息
socket.on('chat_message',(data: mesItem)=>{
  this.setState({
    message:[data,...this.state.message]
  });
})
//发送加入群组
socket.emit('join', {
  roomId:this.props.match.params.roomId,
  userName:this.props.state.name,
  userId:this.props.state.id
})
//发送信息
socket.emit('mes',{
  roomId:this.props.match.params.roomId,
  userName:this.props.state.name,
  userId:this.props.state.id,
  mes:this.state.msg
})

关于 Redux#

redux 跟 vuex 的理念给我的感觉是一样的,同样都是一个状态管理库,并且都是保存在内存当中(刷新就会重置),定义全局 state,触发后修改 state。不同的地方也还是有的,Vuex 的数据是可变可直接修改,Redux 不可变并且是直接用新的 state 替换掉旧的 state。

这个项目用了 react-reduxredux-thunk 两个库。

使用了 react-redux 后流程大大缩短,store 的三大功能:dispatch,subscribe,getState 都让它来帮我们实现了,同时它提供了 Provider 和 Connect,前者是一个组件,后者是一个函数。
大致的流程就是 Provider 组件接受 redux 的 store 作为 props,然后通过 context 往下传,connect 函数收到 Provider 传出的 store,并将 state 和 actionCreator 以 props 传入组件,组件就可以通过调用 props 里的 action 触发 reducer 函数返回新的 state,connect 监听到变化后调用 setState 更新组件并将新的 state 传入。

redux-thunk的作用:可以让 store.dispatch 变成可以接收一个函数 / 一个对象的中间件。

让原本只能接受对象的 store.dispatch 变成可以接收对象 / 方法,并且如果接收了一个方法后自动执行该方法,而不触发 redux 的 store 更新。

最后💻#

感谢 Google、baidu 等搜索引擎和 Google 翻译😵
以及bailicangdu大佬的react-pxq项目的参考以及总结😘

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。