Express路由绑定Controller方法时this.logger未定义问题排查
问题原因
这是典型的JavaScript this 上下文丢失问题:
- 你在路由配置中直接将
componentController.getComponents作为回调函数传递给router.get时,方法脱离了原有的ComponentController实例上下文 - Express触发路由回调时,不会自动绑定控制器实例作为
this的指向,此时方法内部的this不指向你导出的控制器实例,因此访问this.logger会得到undefined - 你在方法内部单独实例化的
test是独立对象,调用它的方法不涉及this绑定,所以test2日志可以正常打印,它和构造函数里初始化的logger不是同一个实例。
修复方案
选任意一种方案即可解决问题:
方案1:路由绑定时显式绑定this
修改路由配置,用bind方法将控制器方法的this永久绑定到控制器实例:
const express = require('express'); const componentController = require('../controllers/component'); const router = express.Router(); // 绑定this到控制器实例 router.get('/components', componentController.getComponents.bind(componentController)); module.exports = router;
方案2:控制器方法改用箭头函数定义
箭头函数没有自身的this,会继承定义时所在上下文(即类实例)的this,无需修改路由代码:
const LogService = require('../services/logService'); class ComponentController { constructor() { this.logger = new LogService('ComponentController'); this.logger.logDebug('test1','test1'); } // 用箭头函数定义类方法 getComponents = async (req, res) => { const test = new LogService('ComponentController'); test.logDebug('test2','test2'); this.logger.logDebug('test3','test3') res.json(''); } } module.exports = new ComponentController();
方案3:路由层包裹匿名函数
在路由回调中显式通过控制器实例调用方法,保证this指向正确:
const express = require('express'); const componentController = require('../controllers/component'); const router = express.Router(); // 包裹一层箭头函数,显式指定调用方 router.get('/components', (req, res) => componentController.getComponents(req, res)); module.exports = router;
内容的提问来源于stack exchange,提问作者A. Hasemeyer
相关产品推荐
相关产品推荐

