Nest.js WebSocketGatewaysでsocket.io確認応答コールバックの使用を有効にしようとしています。
これを出力できるようにしたい:
socket.emit('event', 'some data', function (response) { //do something });
そして、次のようなメッセージハンドラを使用します。
@SubscribeMessage('event')
onStart(client, data, ack) {
//Do stuff
ack('stuff completed');
}
this の問題によると、ライブラリではサポートされていないため、独自のWebSocketアダプタを構築する必要があります。私はそれを試しましたが、それを正確に行う方法がわかりません。 bindMessageHandlers
関数で何か特別なことをする必要があると思いますが、私の試みは無駄でした。これは、フレームワークにバンドルされているデフォルトのsocket.ioアダプターのbindMessageHandlers
実装です。
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)),
);
}
私がこれを実装する方法について誰かが何かポインタを持っていますか?
前もって感謝します!
更新:確認のサポートが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
}
1つの問題は、確認応答関数を提供しない場合、request
は配列ではなく、単にdata
オブジェクトになることです。
私の現在のプロジェクトの1つでは、データと確認応答関数を抽出するヘルパー関数を作成するか、プレースホルダーを作成することでこれに対処しました。つまり、存在を考慮せずに常に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: () => {} }
}
}
古い答え: 現在のところ、これはNestソースを変更しないと不可能です。今後の5.0リリースで追加される予定です。この回答は、リリースされたときに例で更新します。
NestJSを短時間で調査した後。これが私の解決策です。
src
├── app.controller.spec.ts
├── app.controller.ts
├── app.module.ts
├── common
│ └── adapters
│ └── ws-adapter.ts
├── events
│ ├── events.gateway.ts
│ └── events.module.ts
└── main.ts
main.ts
ファイル
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from './common/adapters/ws-adapter.ts';
import * as cors from 'cors';
let corsOptions = {
Origin: 'http://nestjs.test',
credentials: true
}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useWebSocketAdapter(new WsAdapter(3000));
app.use(cors(corsOptions));
await app.listen(4000);
}
bootstrap();
WebSocketアダプターを使用する場合、NestJSアプリケーションで同じポートを使用できなくなったためです。
common\adapters\ws-adapter.ts
ファイル
import * as WebSocket from 'ws';
import { WebSocketAdapter } from '@nestjs/common';
import { IoAdapter } from '@nestjs/websockets';
import { MessageMappingProperties } from '@nestjs/websockets';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/filter';
export class WsAdapter extends IoAdapter {
public bindMessageHandlers(
client,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
) {
handlers.forEach(({ message, callback }) => {
client.on('event', function (data, ack) {
console.log('DATA', data)
ack('woot')
})
Observable.fromEvent(client, message)
.switchMap(data => process(callback(data)))
.filter(result => !!result && result.event)
.subscribe(({ event, data }) => client.emit(event, data))
});
}
}
クライアント側のソースコード
socket.emit('event', {data: 'some data'}, function (response) {
console.log('RESPONSE', response)
});
socket.on('event', function(data) {
console.log('ON EVENT', data);
});
そして、これが私の結果です
この助けを願っています!!
このモジュールを試すことができます: https://www.npmjs.com/package/nestjs-socket-handlers-with-ack 。これは内部で確認応答関数を呼び出します。必要なのは、値を返すか、エラーをスローすることだけです。それが役に立てば幸い
SubscribeMessageからのreturnステートメントを使用するだけです
// server
@SubscribeMessage('message')
async onMessage(
client: Socket, query: string
) {
try {
console.log(query)
return 'hello'
} catch (e) {
// ...
}
}
クライアント側では、3番目のパラメーターとして関数を使用します
// client
this.socket.emit('message', query, (res) => {
console.log(res); // should log 'hello'
});