TypeScript开发Express REST API时调用控制器方法报bidsService未定义错误
问题根因
这个报错的本质是类方法作为路由回调传递时丢失了this上下文绑定。
你在路由层直接把bidsController.createBid的方法引用传给Express路由,当Express内部执行这个方法时,方法内部的this已经脱离了原本的bidsController实例。在TypeScript严格类模式下,这种脱离了对象上下文的方法调用,对应的this会被识别为undefined,访问this.bidsService时自然就会抛出Cannot read property 'bidsService' of undefined的错误。
该问题和路由上挂载的鉴权、角色校验、用户状态校验中间件没有关联。
修复方案
可以根据自己的代码习惯选择任意一种方案解决:
- 路由层传递回调时,用箭头函数锁定实例上下文
修改路由的传参方式,把原来直接传方法引用的逻辑替换为:
箭头函数的this是定义阶段的静态绑定,内部调用router.post('/bids', isAuthenticated, checkRoles(['user']), checkIsVerified, (req, res, next) => bidsController.createBid(req, res, next) );createBid时,方法会正确获取bidsController的实例上下文,不会出现this丢失的问题。 - 将控制器方法定义为箭头函数类属性
修改BidsController的方法写法,让方法在定义时就自动绑定当前实例的this,从根源上避免上下文丢失:
这种写法下可以完全保留原来路由层class BidsController implements IBidsController { bidsService; constructor() { this.bidsService = new BidsService(); } // 以箭头函数形式定义类属性,自带固定this绑定 createBid = async (req: Request, res: Response, next: NextFunction): Promise<void> => { const { params, body } = req; try { validator.bids.create(params, body); const { userId } = res.locals.tokenInfo; const { value } = body; const response = await this.bidsService.createBid(value, userId); res.status(201).json(response); } catch (exception) { next(exception); } } }bidsController.createBid的传参方式,不需要额外包箭头函数,不管这个方法被传递到哪里执行,内部的this都不会偏离控制器实例。 - 在控制器构造函数中手动绑定方法的this
如果习惯保留普通类方法的写法,可以在控制器实例初始化时,手动把方法的this绑定到当前实例上:class BidsController implements IBidsController { bidsService; // 保留原来的普通类方法写法,内部逻辑不需要改动 async createBid(req: Request, res: Response, next: NextFunction): Promise<void> { const { params, body } = req; try { validator.bids.create(params, body); const { userId } = res.locals.tokenInfo; const { value } = body; const response = await this.bidsService.createBid(value, userId); res.status(201).json(response); } catch (exception) { next(exception); } } constructor() { this.bidsService = new BidsService(); // 手动为createBid绑定当前实例的上下文,覆盖实例上的方法引用 this.createBid = this.createBid.bind(this); } }
内容的提问来源于stack exchange,提问作者Gvidas Pranauskas
相关产品推荐
相关产品推荐

