npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

awesome-im

v1.0.7

Published

Lightweight, extensible, JavaScript Instant Messaging.

Downloads

19

Readme

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).


// 静态文件引入 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).


// 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。

{
    "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

{
    "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!"
}

消息、会话相关枚举数据

// 消息类型
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",
}