Express 4 - chaining res.json with promise.then does not work
When you pass res.json
as a function, the res
object gets lost and thus when json()
executes, it has no object and you get the error you are seeing. You can fix that by using .bind()
:
employeeRouter.get("/:id", function(req, res){ Employee.findById(req.params.id).then(res.json.bind(res));});
This will make sure that the res
object stays with your method when the method is executed. Using .bind()
as above is essentially the same as:
employeeRouter.get("/:id", function(req, res){ Employee.findById(req.params.id).then(function(data) { return res.json(data); });});
In fact, .bind()
actually creates a stub function like the anonymous one in the above example. It just does it for you rather than making you do it.
To further example, let's say you had two separate res
objects, res1
and res2
from two separate requests.
var x = res1.json;var y = res2.json;console.log(x === y); // true, no association with either res1 or res2 any more
This is because referencing res1.json
just gets a reference to the .json
method. It uses res1
to get that method (which is fetched from the res1 prototype, but one it has the method, it's just a pointer to the method and there is no longer an association with the object that contained the method. So, when you pass res.json
to a function, you get no attachment to res
. Then when the function you passed res.json
to goes to actually call your function it calls it like this:
var z = res.json;z();
And, when z()
is called, the this
value inside of json
ends up being undefined
and there is no connection to the res
object. Using .bind()
creates a stub function that calls it as res.json(...)
to keep the connection to the object and make sure this
is set properly when the method is executed.