Cách thích hợp để kiểm tra sự tồn tại của biến trong mẫu EJS (sử dụng ExpressJS) là gì?


121

Trên trang github của EJS, có một và chỉ một ví dụ đơn giản: https://github.com/visionmedia/ejs

Thí dụ

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

Điều này dường như đang kiểm tra sự tồn tại của một biến có tên người dùng và nếu nó tồn tại, hãy thực hiện một số thao tác. Duh, phải không?

Câu hỏi của tôi là, tại sao Node lại ném ra một ReferenceError nếu biến người dùng không tồn tại? Điều này làm cho ví dụ trên trở nên vô dụng. Cách thích hợp để kiểm tra sự tồn tại của một biến là gì? Tôi có dự kiến ​​sử dụng cơ chế thử / bắt và lấy ReferenceError đó không?

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)

Tôi hiểu rằng tôi có thể làm cho lỗi này biến mất bằng cách chỉ cần thêm một biến cục bộ "người dùng" trong mã máy chủ của mình, nhưng toàn bộ điểm ở đây là tôi muốn kiểm tra sự tồn tại của các biến như vậy trong thời gian chạy bằng cách sử dụng if / else hàng ngày của bạn kiểu mẫu nullcheck. Một ngoại lệ cho một biến không tồn tại có vẻ vô lý đối với tôi.

Câu trả lời:


149

Bạn có thể làm theo cách tương tự với bất kỳ thứ gì trong js, typeof foo == 'undefined'hoặc vì "local" là tên của đối tượng chứa chúng, bạn có thể làm if (locals.foo). Nó chỉ là js thô: p


3
Tôi bắt đầu tự hỏi liệu mình có gặp phải vấn đề gì lớn hơn không. Điều này cũng gây ra một Lỗi Tham chiếu: <% alert ('test'); %>
Aashay Desai

1
@Aashay alertlà một phần của windowđối tượng của trình duyệt và không có sẵn trong node.js. Cách thay thế là console.log, mặc dù tôi không biết liệu nó có sẵn trong mẫu ejs hay không trừ khi bạn chuyển nó qua locals.
Zikes

2
@Zikes Trong trường hợp này, tôi đang tìm kiếm đặc biệt cho EJS, vì vậy nó nằm trên trang trình duyệt. Nhưng, như TJ đã nói, typeof foo == 'undefined' hoạt động. Tôi học được rằng tôi cũng có thể thêm một !! foo đơn giản nếu foo đã được xác định nhưng là null hoặc rỗng.
Aashay Desai

21
Có một cách viết tắt cho điều này? Tại sao EJS không đơn giản tôn trọng trường hợp if (foo)?
mattdlockyer

5
if (locals.user){ }FTW
s2t2

26

Hãy thử thêm trước biến với locals

Thí dụ: if(locals.user){}


23
<% if (locals.user) { %>

 // Your logic goes here 

<% } %>

13

Bạn có thể tạo trình trợ giúp chế độ xem để kiểm tra "obj === void 0", công cụ này dành cho 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;
}

Sau đó, sử dụng nó trong chế độ xem như

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

3
Tôi không chắc tại sao điều này lại bị từ chối, theo ý kiến ​​của tôi thì nó khá thanh lịch.
joseym,

Sự khác biệt giữa <%=và là <%-gì?
NobleUplift

2
@NobleUplift Theo tài liệu , trong "Thẻ": <%=HTML thoát khỏi giá trị trước; <%-xuất ra giá trị không thoát. Vì vậy, <b>sẽ trở thành một thẻ đậm khi sử dụng <%-, nhưng chỉ đơn giản là dòng chữ "<b>" khi sử dụng<%=
Matheus Avellar

Cảm ơn bạn! Tôi không biết <% - thậm chí là một thẻ hợp lệ.
NobleUplift

13

Để kiểm tra xem người dùng có được xác định hay không, bạn cần thực hiện điều đó:

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

3
Điều này không hoạt động trong thư viện EJS cập nhật nhất (1.0.0). Mặc dù Javascript hợp lệ, EJS sẽ từ chối hoạt động như mong đợi.
Axoren

5
Không làm việc cho tôi. Mặc dù tôi đã định nghĩa foo, mệnh đề else vẫn được đánh giá. Thử nghiệm với EJS 2.3.4 EDIT: sử dụng localsở vị trí của thiscông trình
X_Trust

8

Tôi đã gặp phải vấn đề tương tự khi sử dụng node.js với mongoose / express / ejs khi tạo mối quan hệ giữa 2 tập hợp cùng với mongoose's populate (), trong trường hợp này là admin.user_id tồn tại nhưng có liên quan đến một users._id không tồn tại.
Vì vậy, không thể tìm thấy tại sao:

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

không thành công với "Không thể đọc thuộc tính 'name' của null" Sau đó, tôi nhận thấy rằng tôi cần thực hiện kiểm tra như sau:

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

Tôi cần kiểm tra "vùng chứa" của 'name', vì vậy nó đã hoạt động!
Sau đó, điều này hoạt động tương tự:

if ( !users.user_id ) ...  

Hy vọng nó giúp.


Dù sao, không thể tin rằng có quá ít tài liệu chính thức về EJS ... họ không cập nhật tài liệu của họ kể từ năm 2010 !!!
aesede,

3

Đến trang này để tìm câu trả lời nhưng tôi đã nghĩ ra một cú pháp nội dòng ngắn hơn cho nó, đó là:

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

1
Điều này rất nguy hiểm khi sử dụng, bởi vì nếu đối tượng 'người dùng' không có thuộc tính 'tên', việc hiển thị ejs sẽ không thành công.
Marko Rochevski

1

Đối với iftuyên bố của bạn, bạn cần sử dụng typeof:

<% if (typeof user == 'object' && user) { %>

<% } %>

0

Những gì tôi làm chỉ là chuyển một đối tượng mặc định mà tôi gọi là 'data' = '' và chuyển nó vào tất cả các mẫu ejs của tôi. Nếu bạn cần chuyển dữ liệu thực sang mẫu ejs, hãy thêm chúng làm thuộc tính của đối tượng 'dữ liệu'.

Bằng cách này, đối tượng 'dữ liệu' luôn được xác định và bạn không bao giờ nhận được thông báo lỗi không xác định, ngay cả khi thuộc tính của 'dữ liệu' tồn tại trong mẫu ejs của bạn nhưng không có trong tuyến biểu diễn nút của bạn.


0

Tôi cũng gặp phải vấn đề tương tự và thật may mắn, tôi thấy rằng cũng có một hàm đoản mạch trong JS (tôi biết có một hàm trong Ruby và một số ngôn ngữ khác).

Về phía máy chủ / bộ điều khiển của tôi (đây là từ Node.js / Express):

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

Xem những gì tôi đã làm ở đó? && theo sau một biến có thể không xác định (tức là request.session.survey_resultđối tượng, có thể có hoặc không có dữ liệu biểu mẫu) là ký hiệu ngắn mạch trong JS. Những gì nó làm là chỉ đánh giá phần theo sau && nếu phần ở bên trái của && KHÔNG phải là không xác định. Nó cũng không xuất hiện một lỗi khi phần bên trái IS undefined. Nó chỉ phớt lờ nó.

Bây giờ, trong mẫu của tôi (hãy nhớ rằng tôi đã chuyển đối req.session.survey_result_surveytượng đối tượng vào chế độ xem của tôi là survey_result) và sau đó tôi hiển thị các trường dưới dạng:

<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>

Tôi cũng sử dụng ngắn mạch ở đó, chỉ để giữ an toàn.

Khi tôi đã thử với các cách được đề xuất trước đó, chỉ cần:

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

Đôi khi, nó vẫn cố gắng đánh giá các thuộc tính trong câu lệnh IF ... Có lẽ ai đó có thể đưa ra lời giải thích tại sao?

Ngoài ra, tôi muốn sửa điều đó undefinedcần phải không có dấu nháy đơn, như tôi đã thấy trong các ví dụ trước. Bởi vì điều kiện sẽ không bao giờ đánh giá true, vì bạn đang so sánh giá trị Chuỗi 'undefined'với một kiểu dữ liệu undefined.


0

Bạn có thể sử dụng thủ thuật này:

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

trong đó phạm vi là đối tượng chính của người dùng


0

nếu bạn định sử dụng cùng một đối tượng thường xuyên, bạn có thể sử dụng một hàm như sau:

<% 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;
} %>

sử dụng:

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

0

Tôi đã đưa ra một giải pháp khác.

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

Tôi hi vọng cái này giúp được.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.