以无积分方式表达和调用 response.json 在 Promise.then 中不起作用

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

今天有件事让我很吃惊。我遇到了一堆快速路由处理程序,基本上看起来像这样(还有更多真实的函数调用,但为了易读性:

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

所以我,作为聪明的 javascript 程序员,认为我可以摆脱匿名函数,让 then 函数直接调用 resp.json:

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

但是当我尝试这样做时,我从未得到响应并在节点控制台中看到:

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

在我看来.then(resp.json) and .then (data=>resp.json(data)) 应该是等价的。可以肯定的是,这是一个范围的事情,但我喜欢一个解释,也许还有一个解决方法。

这是因为 resp 是一个具有自身属性的对象,因此 json 函数使用的数据很可能包含在 resp 对象中。

当您将函数 resp.json 本身传递给 then 时,您并没有将 resp 对象或其任何信息与其一起传递。 本质上,then 调用只是 "borrowing" 来自 resp 对象 的函数 json。不过只是函数体本身,没有作用域或隐式值。

更有可能的是,json 的函数体在某处使用了 this,此时您将得到一个无效的(可能是全局的)对象,而不是 resp

要补救,你可以

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

它们不一样,因为 the this operator works in javascript

基本上,resp.json(data)this===resp调用函数,而resp.jsonthis===global调用函数。

要修复它,请传递带有绑定参数的函数 .then(resp.json.bind(resp))(或使用箭头函数)。