When I receive the 'catch' callback, 'this' is undefined, even using arrow funcitions. Any ideas?
private all(req: Request, res: Response): void {
EntityRepository.getRepositoty(req.params.etName).then(repo => {
...
}).catch((err) => {
this.handleError(res, err); // here I get undefined.
});
}
how the all func is called.
It's called based on a Express route.
Added mathod bind as @jfriend00 suggested.
constructor() {
// Connect to database.
DataAccess.connect();
// Starts configuring routes for api
this.router = Router();
// Bad request due to absence of entity type.
this.router.get("/", (req, res) => {
res.statusCode = 400;
res.statusMessage = SysMsgs.error.noEntityTypeSpecified.message;
res.send();
});
// Added method 'bind'.
this.router.get(this.routeBase, this.all.bind(this));
this.router.get(this.routeBase + "/:id", this.findOne.bind(this));
}
With arrow functions, this will retain the value it had in the scope prior to the arrow function call. In your case, that means it will have whatever value this was at the beginning of your all function. So, that value of this depends upon how the all function is called.
And, based on your this.router.get() where you specify this.all as the callback, that means that this inside of all will be set to whatever Express sets it to when it calls that callback. And, that is undefined.
You can fix your issue by using .bind().
this.router.get(this.routeBase, this.all.bind(this));
That will assure that the appropriate this is set when .all() runs. And, then your arrow function inside of all() will use that value of this.
Note: you will need to use .bind() for any method you are passing as a callback where you expect this to be the object inside the callback. When you pass something like this.all, the value of this is lost and only a reference to the method is passed. The caller then calls that method as a normal function with no object binding. You use .bind() to take control of that yourself. .bind() essentially creates a little stub function that reattaches the appropriate this pointer by calling your method using it.
You could also make your own wrapper arrow function for it:
this.router.get(this.routeBase, (req, res) => this.all(req, res));
which as Saravana points out will retain TypeScript type checking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With