此文来讲讲怎么运用Sse大局单向音讯提示发送和物流信息对接。

一、Sse(Server-Send Events)

它是H5的api,用于在服务器和客户端之间实时推送数据流。Sse可以用于完成实时告诉、实时聊天、实时数据更新和实时监控等功能,而且可自动链接,和Websocket不同的是,它是单向的,只允许服务端向客户端实时推送,客户端向服务端发送不了数据音讯。

接下来讲不同文件里完成Sse。

1、首先咱们现在在Nest的项目里创立公共文件,写入项目注册Sse的node事情,来创立和调用Sse,代码如下:

import { EventEmitter } from 'node:events';
export class sseEvent {
  private static sseEvent = new EventEmitter();
  static getEvent () {
    return this.sseEvent
  }
}

2、在事务办法里注册并界说node事情,代码如下:

import { sseEvent } from 'src/common/sseEvent/utils';
sseEvent.getEvent().emit('send', data);

真实事务代码图:先去调用查事务相关表的办法,当然,有些事务场景是可以拿redis的,具体情况根据事务来。

【NestJs】运用Sse 大局单向音讯提示发送和物流信息对接

3、在控制层创立Sse接口并触发方才现已注册好的node 事情,代码如下:

import { Observable, interval, map } from 'rxjs';
import { sseEvent } from 'src/common/sseEvent/utils';
export interface MessageEvent {
  data: object;
}
/** Sse 查询音讯提示数量,可自界说为大局 */
@Sse('clientWeb/getMessageNum')
    async sse(): Promise<Observable<MessageEvent>> {
    return new Observable<any>((observer) => {
      /** 此处触发方才注册好的node事情获取数据 */
      sseEvent.getEvent().on('send', (data: any) => {
        observer.next({ data: data });
      });
    });
}

真实事务代码图:

【NestJs】运用Sse 大局单向音讯提示发送和物流信息对接

那为啥不直接写个查事务相关表的办法在上面调用呢?因为音讯提示是某一个事务场景触发的,打个比方,此时A职工填写好请假条,在create请假条的办法里界说node事情,及时触发Sse发送到审批人手里,总不能去轮询查对应的事务表来触发Sse发送吧。

4、前端代码如下:这儿用的Vue3和Ts

const isNoReadNumber = ref<Number>(); // 未读或者未审批的音讯
const eventSource = new EventSource(`${api}/api/public/clientWeb/getMessageNum`);
eventSource.onmessage = ({ data }) => {
  isNoReadNumber.value = JSON.parse(data)?.isNoReadNumber
}

当然咱们可以获取登录用户的人物来获取对应的音讯提示,用户的信息存在redis,放在大局模块护卫,前端在headers里传过来的token去解析存在redis里对应的人物,来获取某人物的音讯。前提是创立音讯的时候,它得赋予某个人物/某个岗位/某个部分,可用相关表去相关对应的请假条id、人物id/岗位id/部分id。

二、物流信息对接

这儿对接的第三方渠道是快递鸟,可去百度查询,这儿就不贴地址以防说我是打广告的哈。

1、先创立好办法,创立办法前先装置依靠,注意:md5-hex不同的依靠版本对应不同的node版本,自己node版本的是16.18.0,所以装置的是3.0.1版本

装置依靠

npm install md5-hex@3.0.1
npm install querystring

装置好后写一个大局的办法可供其它办法调用,代码如下:

import { Injectable } from '@nestjs/common'
import querystring from 'querystring'
import { HttpService } from '@nestjs/axios'
import { lastValueFrom } from 'rxjs'
import md5Hex from 'md5-hex'
import { GetSettingService } from 'src/system/setting/get.setting.service'
@Injectable()
export class LogisticsService {
  constructor(
    private readonly getSettingService: GetSettingService,
    private readonly http: HttpService,
  ) {}
  // 获取系统设置,(先获取系统设置的快递装备信息)
  async getSettingInfo() {
    let settingInfo = await this.getSettingService.findOneInfo()
    return settingInfo
  }
  // 查询物流
  async sendLogistics() {
    const { logisticsUserId, logisticsKey } = await this.getSettingInfo();
    if (!logisticsUserId) return false; // 没填写用户id
    if (!logisticsKey) return false; // 没填写api的key
    const Url = 'https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx';
    //请求接口指令
    const RequestType  = '1002';
    // 组装应用级参数
    const RequestData = {
      'CustomerName': '',
      'OrderCode': '',
      'ShipperCode': 'STO', // 举个比如,申通快递
      'LogisticCode': '7732684xxxxx', // 物流单号,可动态传进来,这儿举例就写死了
    };
    const DataSign = Buffer.from(md5Hex(JSON.stringify(RequestData)+logisticsKey)).toString('base64')
    const reqParams = {
      RequestType,
      EBusinessID: logisticsUserId,
      DataSign,
      RequestData: JSON.stringify(RequestData),
      DataType: 2
    }
    const headers = {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
    const { data } = await lastValueFrom(this.http.post(Url, querystring.stringify(reqParams), { headers }))
    return data;
  }
}

2、那咱们写个接口来测验测验,代码如下:

Service层


import { LogisticsService } from 'src/common/logistics/logistics.service'
// 后端接口回来封装,可自界说
import { ResultData } from '../../common/utils/result'
@Injectable()
export class SettingService {
  constructor(
      @InjectEntityManager()
      private readonly logisticsService: LogisticsService,
  ) {}
/** 测验查询物流 */
  async sendLogistics() {
    const info = await this.logisticsService.sendLogistics();
    if (!info) return ResultData.fail(AppHttpCode.USER_NOT_FOUND, '查询物流信息失败,请查看对应的装备信息是否填写')
    return ResultData.ok(info);
  }
 }

Controller层

@ApiTags('系统设置模块')
@Controller('setting')
    export class SettingController {
      constructor(private readonly settingService: SettingService) {}
      @Get('/sendLogistics')
      @ApiOperation({ summary: '测验查询物流' })
      @ApiResult()
      async sendLogistics() {
        return await this.settingService.sendLogistics();
      }
}

来看看前端测验的结果,回来正常结果,就说明成功了。

【NestJs】运用Sse 大局单向音讯提示发送和物流信息对接

这就是运用Sse 大局单向音讯提示发送和物流信息对接

以上代码都现已开源了,链接是:gitee.com/wx375149069… 此Nest开源项目包含以下丰富的功能,费事大家点个Start

【NestJs】运用Sse 大局单向音讯提示发送和物流信息对接