nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
66.89k stars 7.56k forks source link

Question about WebSocketGateway class - Emit to specific room from external component #1049

Closed medbejimbj closed 6 years ago

medbejimbj commented 6 years ago

Hi,

I have a WebSocketGateway :

import { Injectable, UseFilters, UseGuards } from '@nestjs/common'; import { OnGatewayConnection, OnGatewayDisconnect, OnGatewayInit, SubscribeMessage, WebSocketGateway, WebSocketServer, WsResponse, } from '@nestjs/websockets';

import { Logger } from '../../common/services'; import { WsGuard } from '../../user/guards'; import { WsExceptionFilter } from '../../common/exception-filters'; import { AuthService } from '../../user/services';

@Injectable() @UseGuards(WsGuard) @UseFilters(WsExceptionFilter) @WebSocketGateway({namespace: 'messages'}) export class MessagesGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect { @WebSocketServer() server;

constructor(private logger: Logger, private authService: AuthService) {
}

afterInit(server) {
    this.logger.warn(`After init`);
}

public async handleConnection(client): Promise<any> {
    this.logger.log(`Client ${client.id} connected`);

    try {
        const user = await this.authService.retrieveUserFromAccessToken(client.handshake.query.auth_token);
        if (user) {
            client.join(user.id);
        }
    } catch (exception) {
        this.logger.warn(`User can not be authenticated`);
    }

}

public handleDisconnect(client): any {
    this.logger.log(`Client ${client.id} disconnected`);
}

@SubscribeMessage('save')
onEvent(client, message: any): WsResponse<any> {
    message.time = new Date();

    this.server.in('1').emit('notifications', {text: 'You have a new message', subject: message});

    client.broadcast.emit('messageSaved', message);

    return {event: 'messageSaved', data: message};
}

} I'm trying to send messages (emit ) to this specific room ("1" on this example) from other parts of the application (others components that can be or not inside the same module).

There is a way to do it without connecting via a socket.io client?

Thanks

kamilmysliwiec commented 6 years ago

Hi @medbejimbj, Honestly, I don't understand. Just to clarify - in order to emit to the specific room, you have to use client instance (there is no other way)

medbejimbj commented 6 years ago

Hello @kamilmysliwiec Otherwise, is there a way to make emit message (in a request after doing some treatments in my API rest services or other services) in the server side and not in client side ?

Thanks

kamilmysliwiec commented 6 years ago

Sure, use the server instance - https://docs.nestjs.com/websockets/gateways (Server)

medbejimbj commented 6 years ago

Yes the problem is that when I do It in my source code I have this error message : TypeError: Cannot read property 'in' of null in addLike function

` import { Logger } from '../../common/services'; import { Action } from '../models/action.entiy'; import { ActionRepository } from '../repositories/action.repository'; import { ActionNameType } from '../enums'; import { EventService } from '../../event/services'; import { Event } from '../../event/models'; import { EventTypeService } from '../../event/services/event-type.service'; import { UserService } from './user.service'; import { WebSocketServer } from '@nestjs/websockets';

@Injectable() export class ActionService { @WebSocketServer() server; constructor(@InjectRepository(ActionRepository) private actionRepository: Repository, private logger: Logger, private eventService: EventService, private eventTypeService: EventTypeService, private userService: UserService) { }

/**
 * Create like action
 * @param userAction
 */
public async addLike(userAction: Action): Promise<Action> {
    console.log(userAction);
    const profileAction = await this.actionRepository.findOne({
        where: {
            creator: userAction.profile,
            profile: userAction.creator,
            course: userAction.course,
            actionName: ActionNameType.like
        }
    });

    if (profileAction) {
        profileAction.actionName = ActionNameType.match;
        userAction.actionName = ActionNameType.match;
        await this.actionRepository.save(profileAction);
        const result = await this.actionRepository.save(userAction);
        this.server.in('1').emit('notifications', {text: 'You have a new message', subject: 'some message'});
        await this.createOnMatchEvent(userAction);
        return result;
    } else {
        return await this.actionRepository.save(userAction);
    }

}`
kamilmysliwiec commented 6 years ago

Please, use StackOverflow for such issues.

lock[bot] commented 4 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.