Robert Moskal Robert Moskal - 3 days ago 5
Javascript Question

Express and calling response.json in a point free fashion doesn't work in Promise.then

Something greatly surprised me today. I cam across a bunch of express route handlers basically look like this (there are more and real function calls, but for the sake of reproducibility:

app.get('/api/foo', (req, resp) => {
Promise.resolve({one: 1})
.then(data=>resp.json(data))
})


So I, as the clever javascript programmer think I can step away from the anonymous function and just let the then function call resp.json directly:

app.get('/api/foo', (req, resp) => {
Promise.resolve({one: 1})
.then(resp.json)
})


But when I try that I never get a response and see this in the node console:


Unhandled promise rejection (rejection id: 1): TypeError: Cannot read
property 'app' of undefined


To my eyes .then(resp.json) and .then(data=>resp.json(data)) should be equivalent. It's a scope thing, to be sure, but I'd love an explanation and perhaps a workaround.

Answer

That's because resp is an object with it's own properties, so more than likely the data that is used by the json function is contained within the response object.

When you pass the function resp.json by itself to then, you aren't passing the resp object, or any of its information, along with it. In essence, the then call is just "borrowing" the function json from the resp object. Just the function body itself though, no scope or implicit values.

More than likely, the content of json uses this somewhere, at which point you will be getting an invalid (probably global) object, instead of resp.

To remedy, you can do

   Promise.resolve({one: 1})
    .then(resp.json.bind(resp))
Comments