无法在Nestjs的WebSocket监听器中调用服务。

huangapple go评论78阅读模式
英文:

Not able to call Service inside WebSocket listener in Nestjs

问题

I have implemented WebSockets in Nestjs using below method and one of the requirement is that I need to update the db once I receive any message from websocket server.
我已经使用以下方法在Nestjs中实现了WebSockets,并且其中一个要求是当我从WebSocket服务器接收到任何消息时,我需要更新数据库。

In order to do that I have done the below code but getting error like this:
为了做到这一点,我已经编写了以下代码,但是出现了以下错误:

But if I call the same method inside any other controller method it works fine(check /test1). Only when I call it from websocket listener I'm getting this error. Even if I call simple method from same controller to just print some log, I'm getting the same error TypeError: this.processData is not a function. Weird!
但是,如果我在任何其他控制器方法内调用相同的方法,它会正常工作(请检查/test1)。只有当我从WebSocket监听器中调用它时,我才会收到此错误。即使我从同一控制器中调用简单的方法来打印一些日志,我也会收到相同的错误TypeError: this.processData is not a function。很奇怪!

Can someone tell me what am I doing wrong with this?
有人可以告诉我我做错了什么吗?

Controller Code :
控制器代码:

import { Controller, Post, Get, Inject, Req, UsePipes, Body, Header,Param } from '@nestjs/common';
import { Request } from 'express';
import * as WebSocket from 'ws';
import { DatabaseService } from '../service/datafetch.service';

@Controller('sample')
export class SampleController {

@Inject(dbService)
private dbService: DatabaseService;

static ws: any;
static wsnew: any;
public receiveDistData = '';

// Connect WS & Listen to messages
constructor() {
    this.initWs();     

    SampleController.ws.on('message', async function incoming(data) {
        console.log('message recieved 8081');
        var dataJson = JSON.parse(data);
        await this.dbService.updateResponseData(dataJson);
        return data;       
    }); 
}

@Get('/test/data/:id')
async testData(@Param('id') id: string) {
    return await this.callWs(id);
}

@Get('/test1/data/:id')
async testData1(@Param('id') id: string) {
    const data = {id: id, data:{}};
    return await this.dbService.updateResponseData(data);
}

async initWs() {
    SampleController.ws = new WebSocket('ws://127.0.0.1:8081');
}

async processData() {
    console.log('Printing a log...');
}

// Data Distribution
async callWs(id) {    
    // If Socket is not opened, try to re-open    
    if(SampleController.ws.readyState != 1) { 
        console.log('Server is dead....');
        this.initWs();
    }
    
    const Data = await this.dbService.findAll(id);
    await SampleController.ws.send(JSON.stringify({
        event: 'channel1',
        data: Data,
    }));
}

}

Repository Code:

import { InjectRepository } from '@nestjs/typeorm';
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { SampleRepository } from '../repository/sample.repository';

@Injectable()
export class SampleService {

constructor(
@InjectRepository(SampleRepository)
private readonly sampleRepository: SampleRepository
) {}

async updateResponseData(data): Promise {
return await this.sampleRepository.updateData(data);
}

}

英文:

I have implemented WebSockets in Nestjs using below method and one of the requirement is that I need to update the db once I receive any message from websocket server.
In order to do that I have done the below code but getting error like this:

But if I call the same method inside any other controller method it works fine(check /test1). Only when I call it from websocket listener I'm getting this error. Even if I call simple method from same controller to just print some log, I'm getting the same error TypeError: this.processData is not a function. Weird!

Can someone tell me what am I doing wrong with this?

(node:11421) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'updateResponseData' of undefined
    at WebSocket.incoming (/opt/dist/controller/sample.controller.js:62:44)
    at WebSocket.emit (events.js:210:5)
    at Receiver.receiverOnMessage (/opt/node_modules/ws/lib/websocket.js:800:20)
    at Receiver.emit (events.js:210:5)
    at Receiver.dataMessage (/opt/node_modules/ws/lib/receiver.js:423:14)
    at Receiver.getData (/opt/node_modules/ws/lib/receiver.js:353:17)
    at Receiver.startLoop (/opt/node_modules/ws/lib/receiver.js:139:22)
    at Receiver._write (/opt/node_modules/ws/lib/receiver.js:74:10)
    at doWrite (_stream_writable.js:431:12)
    at writeOrBuffer (_stream_writable.js:415:5)
    at Receiver.Writable.write (_stream_writable.js:305:11)
    at Socket.socketOnData (/opt/node_modules/ws/lib/websocket.js:875:35)
    at Socket.emit (events.js:210:5)    
    at addChunk (_stream_readable.js:308:12)
    at readableAddChunk (_stream_readable.js:289:11)
    at Socket.Readable.push (_stream_readable.js:223:10)
(node:11421) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:11421) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Controller Code :

import { Controller, Post, Get, Inject, Req, UsePipes, Body, Header,Param } from '@nestjs/common';
import { Request } from 'express';
import * as WebSocket  from 'ws';
import { DatabaseService } from '../service/datafetch.service';

@Controller('sample')
export class SampleController {
    
    @Inject(dbService)
    private dbService: DatabaseService;

    static ws: any;
    static wsnew: any;
    public receiveDistData = '';

    // Connect WS & Listen to messages
    constructor() {
        this.initWs();     

        SampleController.ws.on('message', async function incoming(data) {
            console.log('message recieved 8081');
            var dataJson = JSON.parse(data);
            await this.dbService.updateResponseData(dataJson);
            return data;       
        }); 
    }

    @Get('/test/data/:id')
    async testData(@Param('id') id: string) {
        return await this.callWs(id);
    }

    @Get('/test1/data/:id')
    async testData1(@Param('id') id: string) {
        const data = {id: id, data:{}};
        return await this.dbService.updateResponseData(data);
    }

    async initWs() {
        SampleController.ws = new WebSocket('ws://127.0.0.1:8081');
    }

    async processData() {
        console.log('Printing a log...');
    }
    
    // Data Distribution
    async callWs(id) {    
        // If Socket is not opened, try to re-open    
        if(SampleController.ws.readyState != 1) { 
            console.log('Server is dead....');
            this.initWs();
        }
        
        const Data = await this.dbService.findAll(id);
        await SampleController.ws.send(JSON.stringify({
            event: 'channel1',
            data: Data,
        }));
    }

}

Repository Code:

import { InjectRepository } from '@nestjs/typeorm';
import { Injectable } from '@nestjs/common';
import { Repository } from 'typeorm';
import { SampleRepository } from '../repository/sample.repository';

@Injectable()
export class SampleService {

  constructor(
    @InjectRepository(SampleRepository)
    private readonly sampleRepository: SampleRepository
  ) {}

  async updateResponseData(data): Promise<any> {
    return await this.sampleRepository.updateData(data);
  }

}

答案1

得分: 4

在匿名函数内部,this 指的是全局对象,而不是你的服务实例。

相反,你可以使用箭头函数。在这里,this 指的是类实例,就如你所期望的:

async function(data) {
  // this 是全局对象
  this.call();
}

(data) => {
  // this 与封闭对象相同
  this.call();
}
英文:

Inside an anonymous function, this refers to the global object, not the instance of your service.

Instead you can use an arrow function. Here, this refers to the class instance, as you would expect:

async function(data) {
  // this is global object
  this.call();


(data) => {
  // this is the same as in enclosing object
  this.call();

huangapple
  • 本文由 发表于 2020年1月6日 19:59:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/59611737.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定