10-react即时通讯

231 阅读1分钟

一、实现

socket.js

1. 使用的模块

socket.io: github.com/socketio/so…

nodemon: www.npmjs.com/package/nod…

yarn add nodemon socket.io

2. 具体实现

1. 初始化npm

npm init

2. 修改package.json文件

{
  "name": "soket",
  "version": "1.0.0",
  "description": "chat",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "nodemon": "^2.0.20",
    "socket.io": "^4.5.4"
  }
}

3. socket启动文件

// 开启socket
const io = require("socket.io")(8900, {
  // 允许这个地址访问
  cors: {
    origin: "http://localhost:3000",
  },
});

// 所有在线人的存储
let users = [];

const addUser = (userId, socketId) => {
  !users.some((user) => user.userId === userId) &&
    users.push({ userId, socketId });
};

const removeUser = (socketId) => {
  users = users.filter((user) => user.socketId !== socketId);
};

const getUser = (userId) => {
  return users.find((user) => user.userId === userId);
};

io.on("connection", (socket) => {

  //添加用户信息 和 当前socket的ID
  socket.on("addUser", (userId) => {
    addUser(userId, socket.id);
    io.emit("getUsers", users);
  });

  //监听客户端的信息。并且根据socketID发送出去
  socket.on("sendMessage", ({ senderId, receiverId, text }) => {
    const user = getUser(receiverId);
    io.to(user.socketId).emit("getMessage", {
      senderId,
      text,
    });
  });

  //断开链接重新发送在线人数
  socket.on("disconnect", () => {
    removeUser(socket.id);
    io.emit("getUsers", users);
  });
});

client 前端

1. 使用的模块

socket.io-client: github.com/socketio/so…

yarn add socket.io-client

2. 具体实现

1. 消息界面messenger.jsx

import { io } from 'socket.io-client';

// 初始化
useEffect(() => {
  // 建立socket链接
    socket.current = io('ws://localhost:8900');
  // 开启监听socket发送的信息
    socket.current.on('getMessage', (data) => {
      setArrivalMessage({
        sender: data.senderId,
        text: data.text,
        createdAt: Date.now(),
      });
    });
  }, []);

// 用于记录链接用户信息
useEffect(() => {
  // 每个用户登录都会记录一个
    socket.current.emit('addUser', user._id);
  
  // 获取所有在线的人
    socket.current.on('getUsers', (users) => {
      setOnlineUsers(
        user.followings.filter((f) => users.some((u) => u.userId === f))
      );
    });
  }, [user]);

// 用接口发消息时 也对socket 发一次请求
const handleSubmit = async (e) => {
    e.preventDefault();
    const message = {
      sender: user._id,
      text: newMessage,
      conversationId: currentChat._id,
    };

    const receiverId = currentChat.members.find(
      (member) => member !== user._id
    );
		
  // socket 发一次请求
    socket.current.emit('sendMessage', {
      senderId: user._id,
      receiverId,
      text: newMessage,
    });

  // 接口也发一次
    try {
      const res = await axios.post('/messages', message);
      setMessages([...messages, res.data]);
      setNewMessage('');
    } catch (err) {
      console.log(err);
    }
  };

二、问题

1. 连接不上数据库

1. 报错信息

MongooseError: Operation ‘users.insertOne()’ buffering timed out after 10000ms

2. 解决方案

1. 新建云端数据库
1. 官网地址

account.mongodb.com/account/log…

2.创建一个Database

image-20230202085736800.png

3. 获取链接

image-20230202090227010.png

image-20230202090441266.png

image-20230202090830289.png

2. 在api项目中创建.env 文件
MONGO_URL = mongodb+srv://jrl:qq2236954952@cluster0.ziak0ct.mongodb.net/?retryWrites=true&w=majority