# 介绍

cool-admin即时通讯组件基于socket.io (opens new window)封装,结合redis时其能在多进程的场景下同步消息。

# 安装socket插件

yarn add midwayjs-cool-socket
import { App, Configuration } from '@midwayjs/decorator';
import { ILifeCycle, IMidwayContainer } from '@midwayjs/core';
import { Application } from 'egg';
import * as orm from '@midwayjs/orm';
import * as cool from 'midwayjs-cool-core';
import * as wxpay from 'midwayjs-cool-wxpay';
import * as oss from 'midwayjs-cool-oss';
import * as redis from 'midwayjs-cool-redis';
import * as queue from 'midwayjs-cool-queue';
import * as alipay from 'midwayjs-cool-alipay';
import * as socket from 'midwayjs-cool-socket';

@Configuration({
  // 注意组件顺序 cool 有依赖orm组件, 所以必须放在,orm组件之后 cool的其他组件必须放在cool 核心组件之后
  imports: [
    // 必须,不可移除, https://typeorm.io  打不开? https://typeorm.biunav.com/zh/
    orm,
    // 必须,不可移除, cool-admin 官方组件 https://www.cool-js.com
    cool,
    // 将缓存替换成redis
    redis,
    // socket
    socket,
  ],
})
export class ContainerLifeCycle implements ILifeCycle {
  @App()
  app: Application;
  // 应用启动完成
  async onReady(container?: IMidwayContainer) {}
  // 应用停止
  async onStop() {}
}

WARNING

socket组建依赖redis组建,使其能在多进程的情况下同步消息

# 服务端

import { Config, Provide, Scope, ScopeEnum } from '@midwayjs/decorator';
import { InjectEntityModel } from '@midwayjs/orm';
import { CoolSocket, SocketEnvent } from 'midwayjs-cool-socket';
import { Socket } from 'socket.io';
import { ChatUserEntity } from '../entity/user';
import { Repository } from 'typeorm';

import * as jwt from 'jsonwebtoken';

/**
 * socket的事件
 */
@Provide()
@Scope(ScopeEnum.Singleton)
@CoolSocket() // 支持设置命名空间 如:@CoolSocket('/test') 
export class SocketHandler {
  // 获得模块的配置信息
  @Config('module.chat.jwt')
  jwtConfig;

  @InjectEntityModel(ChatUserEntity)
  chatUserEntity: Repository<ChatUserEntity>;
  /**
   * 连接成功
   * @param data
   */
  @SocketEnvent()
  async connection(socket: Socket) {
    console.log('socket事件', socket.id, socket.handshake.query);
    const { token } = socket.handshake.query;
    let tokenInfo;
    try {
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      tokenInfo = jwt.verify(token, this.jwtConfig.secret);
    } catch (error) {
      // 如果验证不通过则断开连接
      socket.emit('comm', 'token校验失效');
      socket.disconnect();
      return;
    }
    socket.on('disconnect', eventSocket => {
      console.log('断开连接');
    });
    socket.on('msg', msg => {
      console.log('客户端消息', msg);
    });
  }
}

# 获得io对象

@Inject()
socketHandler: SocketHandler

// 这个io对象对应 SocketHandler的命名空间
this.socketHandler.io

TIP

示例中的方法名既socket.io的事件名。@CoolSocket('/test') 则表示为该socket配置了个命名空间,比如不同模块的socket服务可以以此来区分。

# 其他socket.io的配置

/**
 * cool的配置
 */
 export default {
    cool: {
        socket: {
            // 这里是socket.io配置,详见socket.io文档
        }
    },
};

# 客户端

const io = require('socket.io-client');

const socket = io("http://127.0.0.1:8001?token=123");

socket.on('data', (msg)=>{
    console.log('服务端消息', msg)
})

# 跨域

config.cool = {
    socket: {
      cors: {
        // 这里可以写具体的地址如:http://127.0.0.1:8080
        origin: '*',
        methods: ['GET', 'POST'],
      },
    },
  };