NodeJS类中this指向错误致sendKafkaRequest调用失败问题排查
问题:类封装Node子进程message事件处理时出现
this指向错误 我正在用NextJS与NodeJS搭建前后端通信机制,NextJS API会fork一个Node子进程,由该子进程监听来自API的请求。但用类封装代码时,API发送第一条消息触发message事件时,出现如下错误:
this.sendKafkaRequest(message); ^ TypeError: this.sendKafkaRequest is not a function
而用普通函数实现相同逻辑时,代码可正常运行。
类封装代码
import * as Utils from './util' import {ConnectionHandler} from "./ConnectionHandler"; import { KafkaMessagePackage, KafkaResultPackage, NET_KAFKARESPONSE_PACKAGE, NET_PONG_PACKAGE, NetworkPackage, NOT_ENOUGH_ARGUMENTS_ERROR, PACKAGECODE_PING_PACKAGE, SyncPackage, UNKNOWN_PACKAGE_ID, WRONG_NODE_TYPE_ERROR } from "./Variables"; import {Manager} from "./KafkaManager"; const nprocess = require("node:process") const prefix = "[NODEJS] " // Argument Handling const args:Array<string> = nprocess.argv; const arg:string = args[2]; if(arg == undefined || arg != '-f'){ Utils.killProcess(nprocess,NOT_ENOUGH_ARGUMENTS_ERROR); } class myClass { public validateMyRequest(json_message:any){ const message:NetworkPackage = json_message != undefined ? json_message : JSON.parse(json_message); switch (message.reqID) { case PACKAGECODE_PING_PACKAGE: this.sendProcessCreatedPackage(); break; case 0: this.sendKafkaRequest(message); this.sendKafkaResponsePackage(); break; default: this.logError(prefix + UNKNOWN_PACKAGE_ID) break; } } private sendKafkaRequest(message:any) { const kafkaManager:Manager = new Manager(message.hostIP); kafkaManager.sendMessageToKafka(message.topic,message.message); } private sendKafkaResponsePackage() { if(!process.send){ this.logError(prefix + WRONG_NODE_TYPE_ERROR); return; } this.sendMessage(NET_KAFKARESPONSE_PACKAGE); } private sendProcessCreatedPackage(){ this.sendMessage(NET_PONG_PACKAGE) } private sendMessage(messagePacke:KafkaResultPackage):void private sendMessage(messagePackage:SyncPackage):void { if(process.send){ process.send(messagePackage); } } private logError(errorMessage:string):void{ console.log(errorMessage) } } process.on("message", validateMyRequest) // @ts-ignore process.send(NET_PONG_PACKAGE);
普通函数实现代码
import * as Utils from './util' import { KafkaMessagePackage, KafkaResultPackage, NET_KAFKARESPONSE_PACKAGE, NET_PONG_PACKAGE, NetworkPackage, NOT_ENOUGH_ARGUMENTS_ERROR, PACKAGECODE_PING_PACKAGE, SyncPackage, UNKNOWN_PACKAGE_ID, WRONG_NODE_TYPE_ERROR } from "./Variables"; import {Manager} from "./KafkaManager"; const nprocess = require("node:process") const prefix = "[NODEJS] " // Argument Handling const args:Array<string> = nprocess.argv; const arg:string = args[2]; if(arg == undefined || arg != '-f'){ Utils.killProcess(nprocess,NOT_ENOUGH_ARGUMENTS_ERROR); } function validateMyRequest(json_message:any){ const message:NetworkPackage = json_message != undefined ? json_message : JSON.parse(json_message); switch (message.reqID) { case PACKAGECODE_PING_PACKAGE: sendProcessCreatedPackage(); break; case 0: logError("noch alles fein!"); console.log("Hier soll es anscheinend zu einem Fehler kommen:"); console.log(message); sendKafkaRequest(message); sendKafkaResponsePackage(); break; default: logError(prefix + UNKNOWN_PACKAGE_ID) break; } } function sendKafkaRequest(message:any) { const kafkaManager:Manager = new Manager(message.hostIP); kafkaManager.sendMessageToKafka(message.topic,message.message); } function sendKafkaResponsePackage() { if(!process.send){ logError(prefix + WRONG_NODE_TYPE_ERROR); return; } sendMessage(NET_KAFKARESPONSE_PACKAGE); } function sendProcessCreatedPackage(){ sendMessage(NET_PONG_PACKAGE) console.log("Hier isst noch alles fein 1!") } function sendMessage(messagePackage:any):void { if(process.send){ console.log("[NODE] Nachricht gesendet:") console.log(messagePackage); process.send(messagePackage); } } function logError(errorMessage:string):void{ console.log(errorMessage) } process.on("message",validateMyRequest) // @ts-ignore process.send(NET_PONG_PACKAGE);
问题原因
核心是类方法的this上下文丢失:
- 当直接把
validateMyRequest作为回调传给process.on时,该方法会脱离myClass实例的上下文执行。此时this指向的是触发事件的process对象,而非类实例,因此找不到类的私有方法sendKafkaRequest。 - 普通函数版本的所有函数都处于模块作用域中,调用时无需依赖
this,因此没有上下文问题。
解决办法
方法1:创建类实例并绑定this
先实例化类,再用bind把方法的this绑定到实例:
const instance = new myClass(); process.on("message", instance.validateMyRequest.bind(instance));
方法2:用箭头函数包裹回调
通过箭头函数保留实例的上下文:
const instance = new myClass(); process.on("message", (msg) => instance.validateMyRequest(msg));
方法3:在类中用箭头函数定义方法
箭头函数会自动捕获类实例的this,确保方法始终指向实例:
class myClass { // 改为箭头函数 public validateMyRequest = (json_message:any) => { const message:NetworkPackage = json_message != undefined ? json_message : JSON.parse(json_message); switch (message.reqID) { case PACKAGECODE_PING_PACKAGE: this.sendProcessCreatedPackage(); break; case 0: this.sendKafkaRequest(message); this.sendKafkaResponsePackage(); break; default: this.logError(prefix + UNKNOWN_PACKAGE_ID) break; } } // 其他方法保持不变 } // 实例化后直接绑定 const instance = new myClass(); process.on("message", instance.validateMyRequest);
内容的提问来源于stack exchange,提问作者Pixel2203
相关产品推荐
相关产品推荐

