英文:
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();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论