UNPKG

awesome-im

Version:

Lightweight, extensible, JavaScript Instant Messaging.

278 lines (247 loc) 7.89 kB
## IM Lightweight, extensible, JavaScript Instant Messaging. ### 功能 1. 异常断开时,内部实现自动重连(下面几种方式即可无限重连)的情况: 1. 服务端断网 2. 服务端重启 3. 客户端断网 2. 不会自动重连的情况: 1. 客户端主动断线(im.disconnect()) 2. 服务端主动断线(需要服务端发送一个断开连接的标识(前后端约定),在 MESSAG 监听到后,调用im.disconnect()) 3. 心跳机制。 4. 监听客户端的连接状态 5. 设置ping间隔 6. 设置userId 7. 区分会话类型(在发送消息时确定) 1. server:0 server <-> user 2. 单聊:1 user1 <-> user2 8. 消息发送(默认时server会话类型) 1. 文字消息 2. 图片消息 3. 文件消息 4. ping消息(内置) 5. 信令消息(在与服务交互时使用) 9. 监听 1. 消息监听 2. 连接状态监听 10. 信令消息的库扩展性(客户端和服务端可根据约定signalName实现业务层逻辑) 11. 透传服务端发送的消息(content的消息透传) ### 注意事项 1. 客户端主动发送消息,服务端收到消息并返回,从而形成一个闭环,才能证明客户端发送消息成功了。通过messageId才能形成闭环,也就是在客户端主动发消息情况下,服务端需返回客户端携带的messageId。客户端在send回调中拿到消息。 2. 服务端主动给客户端发送消息不用携带messageId,客户端在消息监听中获取到消息。 3. 需要在连接成功(监听 STATUS 为表示连接成功)后,才能发送消息、监听消息。 ### Usage #### NPM、AMD and CommonJS module 参见集成客户端 demo(需注意:当前没有连接服务端)({your app path}/node_modules/awesome-im/src/example/client.html). ```js // 静态文件引入 awesome-im // <script src="${path}awesome-im/dist/index.umd.js"></script> // npm 安装、引入 // npm i awesome-im@latest // import im from "awesome-im" // websocket 地址 const url = "ws://localhost:8088"; // 初始化 im.init({ pingGap: 6000, userId: "allenye" // 自定义用户ID }); // 连接 im.connect(url).then(res => { console.log("connect ->", res) }) // 监听连接状态 im.addEventListener("STATUS", evt => { console.log("连接状态->", evt) }) // 监听消息 im.addEventListener("MESSAGE", evt => { console.log("监听消息->", evt) }) // 发送信令消息 im.send(new im.Message.SignalMessage({ signalName: "start", // 信令名称自定义,与服务端约定。 // signalName: "end", to: "server" })).then(res => { console.log("发送SignalMessage成功", res) }) // 发送文字消息 im.send(new im.Message.TextMessage({ // message: "message 可以扩展" message: { test: 123, array: [123, 456], object: { name: "allen" } }, from: "allen", to: "server" })).then(res => { console.log("发送TextMessage成功 ->", res) }) // 修改会话类型(需要设置 conversationType),需要注意需要服务处理 user1、user2 之间的通信。 // 默认时server会话(im.Message.ConversationType.SERVER) im.send(new im.Message.TextMessage({ conversationType: im.Message.ConversationType.PRIVATE, // 单聊会话 message: "发送一条单聊会话消息", from: "user1", to: "user2" })).then(res => { console.log("发送TextMessage成功 ->", res) }) ``` ### 服务端 demo 参见集成服务端nodejs demo ({your app path}/node_modules/awesome-im/src/example/server.js). ```js // nodejs const WebSocket = require('ws'); const { encode, decode } = require("@msgpack/msgpack"); const server = new WebSocket.Server({ port: 8088 }); server.on('connection', (socket) => { console.log('Client connected'); // setInterval(() => { // server.clients.forEach((client) => { // client.send(encode({ // code: ErrorCode.SUCCESS, // data: { // messageType: MessageType.SIGNAL, // sentTime: new Date().getTime(), // messageUId: 'CBE5-1922-F8C9-730B', // conversationType: ConversationType.SERVER, // to: 'allen', // signalName: 'end', // from: 'server', // content: { // message: "一条服务端发送的消息" // }, // }, // errMsg: "success!" // })); // }) // }, 2000); // 当接收到消息时,向所有连接的客户端广播消息 socket.on('message', (message) => { // console.log(`Received message: ${message}`); const _data = decode(message) server.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { const data = { ..._data, time: new Date().getTime() } console.log(data) client.send(encode({ code: ErrorCode.SUCCESS, data: data })); } }); }); // 当连接关闭时,向所有连接的客户端广播消息 socket.on('close', () => { console.log('Client disconnected'); server.clients.forEach((client) => { if (client.readyState === WebSocket.OPEN) { client.send(encode({ errMsg: "close", code: 4 })); } }); }); }); ``` #### 服务返回数据格式 服务端主动发送消息,不用携带 messageId。 ```json { "code": 0, "data": { "messageType": "SignalMsg", "sentTime": 1681900543414, "messageUId": "CBE5-1922-F8C9-730B", "conversationType": 0, "to": "allen", "signalName": "login", // 可扩展 "from": "server", "messageDirection": 2 }, "errMsg": "success!" } ``` 服务端收到客户端发送的消息后(服务端发送闭环消息),需要携带messageId ```json { "code": 0, "data": { "messageType": "TextMsg", "sentTime": 1681900543414, "messageId": "**需要携带客户端发送消息的messageId,从而达到闭环。**", "messageUId": "CBE5-1922-F8C9-730B", "conversationType": 0, "to": "allen", "signalName": "end", // 可扩展 "from": "server", "content": { // 可以扩展 "message": "客户端发送消息后,服务端需要返回一条消息(闭环)。证明客户端发送的消息成功了。" }, "messageDirection": 2 }, "errMsg": "success!" } ``` ### 消息、会话相关枚举数据 ```js // 消息类型 export const MessageType = { TEXT: "TxtMsg", IMAGE: "ImgMsg", FILE: "FileMsg", PING: "PingMsg", SIGNAL: "SignalMsg" } // 会话类型 export const ConversationType = { /** * 客户端与服务端的会话 */ SERVER: 0, /** * 单聊 */ PRIVATE: 1, /** * 讨论组 */ DISCUSSION: 2, /** * 群组聊天 */ GROUP: 3, /** * 聊天室会话 */ CHATROOM: 4, /** * 系统消息 */ SYSTEM: 5, } // 消息方向 export const MessageDirection = { /** * 发送消息。 */ SEND: 1, /** * 接收消息。 */ RECEIVE: 2 } // 事件监听 const event = { STATUS: "STATUS", MESSAGE: "MESSAGE", TEST: "TEST", } ```