2016-11-30 4 views
3

Что-то меня очень удивило сегодня. Я кулачок через кучу экспресс обработчиков маршрутов в основном выглядеть следующим образом (есть более и реальные вызовов функций, но ради воспроизводимости:Экспресс и вызов response.json в точке бесплатной моды не работает в Promise.then

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

Так что я, как умный Javascript программист думает, что я могу отойти от анонимная функция и просто дайте 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) и .then (данные => resp.json (данные)) должны быть эквивалентны. Конечно, это предмет охвата, но мне бы хотелось объяснить и, возможно, обходной путь.

ответ

4

Это потому, что resp является объектом с его собственными свойствами, поэтому более вероятно, данные, используемые функцией json содержится внутри resp объекта.

При передаче функции resp.json самих по себе в then, вы не передавая resp объекта, или любой из его информации, вместе с ним. По сути, звонок then просто «заимствует» функцию json от resp объект. Просто тело функции, хотя и не имеет видимых или неявных значений.

Более вероятно, функция тела json использует this где-то, в какой момент вы будете получать недействительный (вероятно, глобальный) объект, а не resp.

Чтобы исправить, вы можете сделать

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

Ha. Ты прав. Я просто понял это. Благодаря! Но его «уродливый» способ может также использовать функцию толстой стрелки. –

3

Они не то же самое из-за того, как the this operator works in javascript.

В принципе, resp.json(data) вызывает функцию с this===resp, а resp.json вызывает функцию с this===global.

Чтобы исправить это, передайте функцию с привязанными параметрами .then(resp.json.bind(resp)) (или используйте функцию стрелки).