2015-07-02 1 views
1

Это странный вопрос, но следуйте за мной. У меня есть nodejs-сервер с явным приложением. Внутри приложения, я устанавливаю мои местные житель следующим образом:NodeJS Express app.locals не доступны непосредственно в функции

var moment = require('moment'); 
app.locals.moment = moment; 

EJS визуализируются как:

exports.page = function (req, res) { 
    res.render('first-page'); 
}; 

Тогда в моей EJS, у меня есть следующий код:

<% 
if (!moment) { 
    throw new Error('moment is not defined'); 
} 
function formatDate(date) { 
    return moment(date).format(); 
} 
%> 
<p><%= formatDate(1435856054045); %></p> 

Интересно, что этот момент не вызывает исключения. Таким образом, он определяется в области ejs, как говорит документация. Однако исключение вызывает ejs, говорящий, что момент не определен в formatDate. Если я изменил formatDate на следующее, все будет работать.

function formatDate(date) { 
    return locals.moment(date).format(); 
} 

Мой вопрос в том, как функции, определенные в ejs, имеют область действия и какой контекст применяется к ним. Использует ли ejs другой контекст функции, чем плавающий javascript? Я предполагаю, что он делает что-то вроде formatDateFunctionPointer.call(ejsScope, ...);

ответ

2

Проблемы становится ясно, когда у вас есть ejs вывода генерируемых функций (к которой шаблон компилируется):

with (locals || {}) { 
    if (!moment) { 
     throw new Error('moment is not defined'); 
    } 
    function formatDate(date) { 
    return moment(date).format(); 
    } 
    ... 
} 

Проблема заключается в том, что ваша formatDate функции водрузила за пределами блока with; внутри этот блок, moment есть фактически locals.moment, поэтому ваш тест, если он существует, работает.

Однако, когда вы можете formatDate, это не работает в контексте with блока, и, следовательно, moment не существует (но locals.moment делает, как вы уже выяснили).

Вот автономный пример задачи:

var obj = { test : 123 }; 
with (obj) { 
    if (test !== 123) throw new Error('test does not equal 123'); 
    function showTest() { 
    console.log('test', test); 
    } 
    showTest(); 
} 

Одним из способов решения этой проблемы является использование функции выражения:

<% 
if (typeof moment === 'undefined') { 
    throw new Error('moment is not defined'); 
} 
var formatDate = function(date) { 
    return moment(date).format(); 
}; 
%> 
<p><%= formatDate(1435856054045); %></p> 

(он также фиксирует тест, чтобы увидеть, если moment на самом деле)

Или вы можете установить EJS _with на false.

+0

Сладкий, спасибо. Имеет смысл. Опубликованный код был просто упрощением моего настоящего, но вы сделали очень важную часть! – Vadym