在EJS模板中检查变量是否存在的正确方法是什么(使用ExpressJS)?

时间:2011-03-21 00:09:21

标签: node.js express ejs

在EJS github页面上,只有一个简单的例子: https://github.com/visionmedia/ejs

实施例

<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>

这似乎是在检查是否存在名为user的变量,如果存在,请执行一些操作。呃,对吧?

我的问题是,如果用户变量不存在,为什么Node会抛出一个ReferenceError?这使得上面的例子变得毫无用处。检查变量是否存在的合适方法是什么?我是否希望使用try / catch机制并获取ReferenceError?

ReferenceError: user is not defined
    at IncomingMessage.anonymous (eval at <anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:140:12))
    at IncomingMessage.<anonymous> (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:142:15)
    at Object.render (/usr/local/lib/node/.npm/ejs/0.3.1/package/lib/ejs.js:177:13)
    at ServerResponse.render (/usr/local/lib/node/.npm/express/1.0.7/package/lib/express/view.js:334:22)
    at Object.<anonymous> (/Users/me/Dropbox/Projects/myproject/server.js:188:9)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)
    at pass (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:162:10)
    at /usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:152:27
    at Object.restrict (/Users/me/Dropbox/Projects/myproject/server.js:94:5)
    at param (/usr/local/lib/node/.npm/connect/0.5.10/package/lib/connect/middleware/router.js:146:21)

我知道我可以通过在我的服务器代码中添加“用户”局部变量来消除此错误,但这里的重点是我想在运行时使用您的每一天检查这些变量是否存在if / else nullcheck type pattern。不存在的变量的例外对我来说似乎很荒谬。

15 个答案:

答案 0 :(得分:120)

与js,typeof foo == 'undefined'中的任何内容相同,或者因为“locals”是包含它们的对象的名称,您可以执行if (locals.foo)。这只是原始的js:p

答案 1 :(得分:20)

尝试使用 locals

预先添加变量

示例:if(locals.user){}

答案 2 :(得分:14)

<% if (locals.user) { %>

 // Your logic goes here 

<% } %>

答案 3 :(得分:11)

您可以创建一个查看“obj === void 0”的视图助手,这个用于express.js:

res.locals.get = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    var path = args[0].split('.');
    var root = this;
    for (var i = 0; i < path.length; i++) {
        if(root[path[i]] === void 0) {
            return args[1]?args[1]:null;
        } else {
            root = root[path[i]];
        }
    };
    return root;
}

然后在视图中使用它

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value

答案 4 :(得分:11)

要检查用户是否已定义,您需要这样做:

<% if (this.user) { %>
   here, user is defined
<% } %>

答案 5 :(得分:5)

我在使用mongoose / express / ejs时将node.js与mongoose的populate()结合使用时遇到了同样的问题,在这种情况下,admins.user_id存在但与不相关的用户有关。 _id。
所以,找不到原因:

if ( typeof users.user_id.name == 'undefined' ) ...

失败了“无法读取属性'名称'为null” 然后我注意到我需要像这样进行检查:

if ( typeof users.user_id == 'undefined' ) ...

我需要检查“名称”的“容器”,所以它有效! 在那之后,这也是一样的:

if ( !users.user_id ) ...  

希望它有所帮助。

答案 6 :(得分:2)

来到此页面寻求答案,但我想出了一个更短的内联语法:

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>

答案 7 :(得分:1)

对于php.ini语句,您需要使用if

typeof

答案 8 :(得分:0)

我所做的只是传递我呼叫的默认对象&#39;数据&#39; =&#39;&#39;并将其传递给我所有的ejs模板。 如果您需要将实际数据传递给ejs模板,请将它们添加为&#39;数据的属性。对象

通过这种方式,&#39;数据&#39;始终定义对象并且您永远不会得到未定义的错误消息,即使“数据”的属性也是如此。存在于您的ejs模板中,但不存在于您的节点快速路径中。

答案 9 :(得分:0)

我有同样的问题,幸运的是,我发现JS中还有一个短路功能(我知道Ruby和其他一些语言中都有一个)。

在我的服务器/控制器端(这是来自Node.js / Express):

return res.render('result', {survey_result : req.session.survey_result&&req.session.survey_result.survey }); 

看看我在那里做了什么?和&amp;&amp;在可能未定义的变量(即request.session.survey_result对象(可能有或没有形式数据)之后)之后是JS中的短路符号。它的作用只是评估&amp;&amp;和如果&amp;&amp;和左边的部分不是未定义的。当左侧部分为undefined时,它也不会抛出错误。它只是忽略了它。

现在,在我的模板中(记住我将对象req.session.survey_result_survey对象传递给我的视图survey_result),然后我将字段渲染为:

<table>
    <tr>
        <td> Name:</td>
        <td> <%=survey_result&&survey_result.name%></td>
    </tr>
    <tr>
        <td> Dojo Location:</td>
        <td> <%=survey_result&&survey_result.dojo_loc%></td>
    </tr>
    <tr>
        <td> Favourite Language:</td>
        <td> <%=survey_result&&survey_result.fave_lang%></td>
    </tr>

我也在那里使用过短路,只是为了安全保管。

当我尝试以前建议的方式时,只需:

<% if (typeof survey_result !== undefined) { %>
... <!-- some js and/or html code here -->
<% } %>

有时,它仍然会尝试评估IF声明中的属性......也许有人可以解释为什么?

另外,我想纠正undefined需要没有单引号,正如我在前面的例子中看到的那样。因为您要将字符串值true与数据类型'undefined'进行比较,所以条件永远不会计算为undefined

答案 10 :(得分:0)

您可以使用此技巧:

user.name // stops code execution,if user is undefined
(scope.user||0).name // === undefined

其中范围是用户的父对象

答案 11 :(得分:0)

如果您打算经常使用同一对象,则可以使用如下函数:

<% function userObj(obj){
    //replace user with what you name your object
    if(typeof user === 'object'){
        let result = user;
        if(obj){
            obj = obj.split('.');
            for(let i = 0; i < obj.length; i++){
                if(obj[i] && obj[i].trim() !== '' && result[obj[i]]){
                    result = result[obj[i]];
                }else{
                    result = false;
                    break;
                }
            }
        }
        return result;
    }
    return false;
} %>

用法:

<% if(userObj('name')){
    <h2><%= userObj('name') %></h2>
} %>

答案 12 :(得分:0)

我想出了另一种解决方案。

<% if(user){ %>
   <% if(user.name){ %>
     <h1><%= user.name %></h1>
<%}}%>

我希望这会有所帮助。

答案 13 :(得分:0)

这可能对某人有所帮助。

<p><%= locals?.message %></p>

<p><%= locals.message || '' %></p>

答案 14 :(得分:-2)

我在 Joe Andrieu's blog 上找到了我认为更好的解决方案:

<%= user.name ? user.name : '' %>

这适用于比其他答案更多的情况(即,当您需要检查单个属性是否存在时)。