Nest.js中的Socket.io确认

awn*_*ton 10 javascript socket.io nestjs

我正在尝试在Nest.js WebSocketGateways中启用socket.io确认回调.

我希望能够发出这个:

socket.emit('event', 'some data', function (response) { //do something });
Run Code Online (Sandbox Code Playgroud)

并使用这样的消息处理程序:

@SubscribeMessage('event')
onStart(client, data, ack) {
  //Do stuff
  ack('stuff completed');
}
Run Code Online (Sandbox Code Playgroud)

根据这个问题,库中不支持它,所以你必须构建自己的websocket适配器.我尝试过但不确定如何做到这一点.我想我需要在bindMessageHandlers功能上做一些特别的事情,但我的尝试都是徒劳的.这是bindMessageHandlers框架中捆绑的默认socket.io适配器中的实现:

public bindMessageHandlers(
  client,
  handlers: MessageMappingProperties[],
  process: (data: any) => Observable<any>,
) {
  handlers.forEach(({ message, callback }) =>
    Observable.fromEvent(client, message)
      .switchMap(data => process(callback(data)))
      .filter(result => !!result && result.event)
      .subscribe(({ event, data }) => client.emit(event, data)),
  );
}
Run Code Online (Sandbox Code Playgroud)

有没有人对如何实现这个有任何指示?
提前致谢!

ken*_*nny 6

只需使用 SubscribeMessage 的 return 语句

// server
@SubscribeMessage('message')
  async onMessage(
    client: Socket, query: string
  ) {
    try {
      console.log(query) 
      return 'hello'
    } catch (e) {
      // ...
    } 
  }
Run Code Online (Sandbox Code Playgroud)

在客户端使用函数作为第三个参数

// client
this.socket.emit('message', query, (res) => {
  console.log(res); // should log 'hello'
});
Run Code Online (Sandbox Code Playgroud)


Quỳ*_*yễn 5

经过短暂研究 NestJS。\n这是我的解决方案。

\n\n
src\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app.controller.spec.ts\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app.controller.ts\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app.module.ts\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 common\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 adapters\n\xe2\x94\x82\xc2\xa0\xc2\xa0     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 ws-adapter.ts\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 events\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 events.gateway.ts\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 events.module.ts\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.ts\n
Run Code Online (Sandbox Code Playgroud)\n\n

main.ts文件

\n\n
import { NestFactory } from \'@nestjs/core\';\nimport { AppModule } from \'./app.module\';\nimport { WsAdapter } from \'./common/adapters/ws-adapter.ts\';\nimport * as cors from \'cors\';\n\nlet corsOptions = {\n    origin: \'http://nestjs.test\',\n    credentials: true\n}\n\nasync function bootstrap() {\n    const app = await NestFactory.create(AppModule);\n    app.useWebSocketAdapter(new WsAdapter(3000));\n    app.use(cors(corsOptions));\n    await app.listen(4000);\n}\nbootstrap();\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为当我们使用 WebSocket 适配器时,我们不能再与 NestJS 应用程序使用相同的端口。

\n\n

common\\adapters\\ws-adapter.ts文件

\n\n
import * as WebSocket from \'ws\';\nimport { WebSocketAdapter } from \'@nestjs/common\';\nimport { IoAdapter } from \'@nestjs/websockets\';\nimport { MessageMappingProperties } from \'@nestjs/websockets\';\nimport { Observable } from \'rxjs/Observable\';\nimport \'rxjs/add/observable/fromEvent\';\nimport \'rxjs/add/observable/empty\';\nimport \'rxjs/add/operator/switchMap\';\nimport \'rxjs/add/operator/filter\';\n\nexport class WsAdapter extends IoAdapter {\n  public bindMessageHandlers(\n    client,\n    handlers: MessageMappingProperties[],\n    process: (data: any) => Observable<any>,\n  ) {\n    handlers.forEach(({ message, callback }) => {\n        client.on(\'event\', function (data, ack) {\n            console.log(\'DATA\', data)\n            ack(\'woot\')\n        })\n        Observable.fromEvent(client, message)\n            .switchMap(data => process(callback(data)))\n            .filter(result => !!result && result.event)\n            .subscribe(({ event, data }) => client.emit(event, data))\n        });\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的客户端源代码

\n\n
socket.emit(\'event\', {data: \'some data\'}, function (response) {\n    console.log(\'RESPONSE\', response)\n});\nsocket.on(\'event\', function(data) {\n    console.log(\'ON EVENT\', data);\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的结果

\n\n

在此输入图像描述

\n\n

在此输入图像描述

\n\n

希望这有帮助!

\n


awn*_*ton 3

更新: Nest 5.0 中添加了对确认的支持。
如果套接字提供者将多个参数传递到SubscribeMessage处理程序中,则request参数将是包含这些参数的数组。

例如使用默认的 socket.io-adapter:

@SubscribeMessage('event')
async onEvent(client, request) {
  let data = request[0]
  let ack = request[1] //the acknowledgement function
}
Run Code Online (Sandbox Code Playgroud)

一个问题是,如果您不提供确认函数,则该函数request将不是一个数组,而只是一个data对象。

在我当前的一个项目中,我通过创建一个提取数据和确认函数的辅助函数或创建一个占位符来解决这个问题,这意味着我始终可以调用 ack 函数而不考虑它的存在:

export function extractRequest (req: any): { data: any, ack?: Function } {
  if (Array.isArray(req)) {
    const [data, ack] = req
    return { data, ack }
  } else {
    return { data: req, ack: () => {} }
  }
}
Run Code Online (Sandbox Code Playgroud)

旧答案: 目前的状态是,如果不修改 Nest 源代码,这是不可能的。它将在即将发布的 5.0 版本中添加。当这个答案发布时,我将用一个例子来更新它。

来源: https: //github.com/nestjs/nest/issues/581