TypeScript调用getNotesHandler时_service为undefined的问题求助
问题描述
调用getNotesHandler()时出现如下错误:
TypeError: Cannot read properties of undefined (reading '_service') at ... at ... at ...
完整代码如下:
import { Request, ResponseObject, ResponseToolkit } from "@hapi/hapi"; import { ClientError } from "../../exceptions/ClientError"; import { NotesService } from "../../services/inMemory/NotesService"; import { notesValidator, NotesValidator } from "../../validator/notes"; export class NotesHandler { _service: NotesService = new NotesService(); _validator: NotesValidator; constructor(service: NotesService, validator: NotesValidator) { this._service = service; this._validator = validator; console.log('Service initialized', this._service) console.log('Validator initialized', this._validator) } postNoteHandler(request: Request, h: ResponseToolkit): ResponseObject { try { this._validator.validateNotePayload(request.payload); const data: NoteInput = JSON.parse(request.payload.toString()); const noteId = this._service.addNote(data.title, data.body, data.tags); const response = h.response({ status: 'success', message: `Note with id ${noteId} was added`, data: { noteId, } }); response.code(201); return response; } catch(error) { if (error instanceof ClientError) { const response = h.response({ status: 'error', message: error.message, }); response.code(error.statusCode); return response; } // Server Error const response = h.response({ status: 'error', message: 'Internal server error', }); response.code(500); console.error(error); return response; } } getNotesHandler(request: Request, h: ResponseToolkit): ResponseObject { console.log("getNotesHandler"); const notes = this._service.getNotes(); const response = h.response({ status: 'success', message: 'Notes were retrieved', data: notes, }); response.code(200); return response; } getNoteByIdHandler(request: Request, h: ResponseToolkit): ResponseObject { try { const noteId = request.params.id; const note = this._service.getNoteById(noteId); const response = h.response({ status: 'success', data: { note, } }); response.code(200); return response; } catch(error) { if (error instanceof ClientError) { const response = h.response({ status: 'error', message: error.message, }); response.code(error.statusCode); return response; } // Server Error const response = h.response({ status: 'error', message: 'Internal server error', }); response.code(500); console.error(error); return response; } } putNoteByHandler(request: Request, h: ResponseToolkit): ResponseObject { try { this._validator.validateNotePayload(request.payload); const noteId = request.params.id; this._service.editNoteById( noteId, JSON.parse(request.payload.toString()) ); const response = h.response({ status: 'success', message: `Note with id ${noteId} was edited`, }); return response; } catch(error) { if (error instanceof ClientError) { const response = h.response({ status: 'fail', message: error.message, }); response.code(error.statusCode); return response; } // Server ERROR! const response = h.response({ status: 'error', message: 'Server goes error.', }); response.code(500); console.error(error); return response; } } deleteNoteByIdHandler(request: Request, h: ResponseToolkit): ResponseObject { try { const noteId = request.params.id; this._service.deleteNoteById(noteId); const response = h.response({ status: 'success', message: `Note with id ${noteId} was deleted`, }); return response; } catch(error) { if (error instanceof ClientError) { const response = h.response({ status: 'fail', message: error.message, }); response.code(error.statusCode); return response; } // Server ERROR! const response = h.response({ status: 'error', message: 'Server goes error.', }); response.code(500); console.error(error); return response; } } }
构造函数中通过console.log(this._service)验证,控制台输出显示_service已正常初始化:
Service initialized NotesService { _notes: [] } Validator initialized { validateNotePayload: [Function: validateNotePayload] }
但调用getNotesHandler()时,_service和_validator均为undefined,其他类方法存在同样问题。
解决方案
这个问题的核心是类方法的this绑定丢失。当在Hapi中注册路由时,如果直接将handler设置为类的方法(比如handler: notesHandler.getNotesHandler),方法会脱离类实例的上下文执行,导致this指向undefined(严格模式下),自然无法访问_service和_validator。
以下是三种可行的解决方式:
1. 在构造函数中手动绑定this
修改NotesHandler的构造函数,将所有需要用到的方法的this绑定到当前实例:
constructor(service: NotesService, validator: NotesValidator) { this._service = service; this._validator = validator; // 绑定this到类实例 this.postNoteHandler = this.postNoteHandler.bind(this); this.getNotesHandler = this.getNotesHandler.bind(this); this.getNoteByIdHandler = this.getNoteByIdHandler.bind(this); this.putNoteByHandler = this.putNoteByHandler.bind(this); this.deleteNoteByIdHandler = this.deleteNoteByIdHandler.bind(this); console.log('Service initialized', this._service) console.log('Validator initialized', this._validator) }
2. 使用箭头函数定义类方法
箭头函数会自动捕获当前上下文的this,可以直接替换类中的方法定义:
postNoteHandler = (request: Request, h: ResponseToolkit): ResponseObject => { // 原方法内容不变 } getNotesHandler = (request: Request, h: ResponseToolkit): ResponseObject => { // 原方法内容不变 } // 其他方法同理替换为箭头函数
3. 在注册路由时绑定this
如果不想修改类的内部实现,可以在注册Hapi路由时,通过bind指定this为类实例:
const notesHandler = new NotesService(...); server.route({ method: 'GET', path: '/notes', handler: notesHandler.getNotesHandler.bind(notesHandler) });
选择任意一种方式都能解决this指向错误的问题,推荐第一种或第二种,代码更简洁且易于维护。
内容的提问来源于stack exchange,提问作者Muhammad Alif Darmamulia
相关产品推荐
相关产品推荐

