อะไรคือวิธีที่เหมาะสมในการตรวจสอบการมีอยู่ของตัวแปรในเทมเพลต EJS (โดยใช้ ExpressJS)


122

ในหน้า EJS github มีตัวอย่างง่ายๆเพียงตัวอย่างเดียว: https://github.com/visionmedia/ejs

ตัวอย่าง

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

ดูเหมือนว่ากำลังตรวจสอบการมีอยู่ของตัวแปรที่ชื่อผู้ใช้และหากมีอยู่ให้ทำบางอย่าง ดุใช่มั้ย?

คำถามของฉันคือทำไม 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 ข้อยกเว้นสำหรับตัวแปรที่ไม่มีอยู่จริงดูเหมือนจะไร้สาระสำหรับฉัน

คำตอบ:


149

เช่นเดียวกับที่คุณจะทำมันด้วยอะไรใน js, typeof foo == 'undefined'หรือตั้งแต่ "ชาวบ้าน" if (locals.foo)เป็นชื่อของวัตถุที่มีพวกเขาที่คุณสามารถทำได้ มันเป็นแค่ js ดิบ: p


3
ฉันเริ่มสงสัยว่าฉันมีปัญหาใหญ่กว่าในมือหรือเปล่า สิ่งนี้แสดงข้อผิดพลาดในการอ้างอิงด้วย: <% alert ('test'); %>
Aashay Desai

1
@Aashay alertเป็นส่วนหนึ่งของwindowออบเจ็กต์ของเบราว์เซอร์และไม่มีใน node.js ทางเลือกคือconsole.logแม้ว่าผมไม่ทราบว่ามันมีอยู่ในแม่แบบ ejs localsจนกว่าคุณจะผ่านมันผ่าน
Zikes

2
@Zikes ในกรณีนี้ฉันกำลังมองหา EJS โดยเฉพาะดังนั้นจึงอยู่ในหน้าเบราว์เซอร์ แต่เหมือนที่ TJ กล่าว typeof foo == 'undefined' ใช้ได้ผล ฉันได้เรียนรู้ว่าฉันสามารถเพิ่มง่ายๆ !! foo ได้หากกำหนด foo ไว้ แต่เป็นโมฆะหรือว่างเปล่า
Aashay Desai

21
มีชวเลขสำหรับสิ่งนี้หรือไม่? ทำไม EJS ไม่เพียงแค่ให้เกียรติกรณี if (foo)?
mattdlockyer

5
if (locals.user){ }FTW
s2t2



13

คุณสามารถสร้างตัวช่วยดูซึ่งตรวจสอบ "obj === โมฆะ 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

3
ไม่แน่ใจว่าทำไมสิ่งนี้จึงถูกลดลงมันค่อนข้างสง่างามในความคิดของฉัน
joseym

อะไรคือความแตกต่างระหว่าง<%=และ<%-?
NobleUplift

2
@NobleUplift ตามเอกสารภายใต้ "แท็ก": <%=HTML จะหลีกเลี่ยงค่าก่อน <%-ส่งออกค่าที่ไม่ใช้ Escape ดังนั้น<b>จะกลายเป็นแท็กตัวหนาเมื่อใช้<%-แต่เพียงแค่ข้อความ "<b>" เมื่อใช้<%=
Matheus Avellar

ขอบคุณ! ฉันไม่รู้เลยว่า <% - เป็นแท็กที่ถูกต้องด้วยซ้ำ
NobleUplift

13

ในการตรวจสอบว่ามีการกำหนดผู้ใช้หรือไม่คุณต้องทำดังนี้:

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

3
สิ่งนี้ใช้ไม่ได้ในไลบรารี EJS ล่าสุด (1.0.0) แม้ว่า Javascript ที่ถูกต้อง EJS จะปฏิเสธที่จะดำเนินการตามที่คาดไว้
Axoren

5
ไม่ได้ผลสำหรับฉัน แม้ว่าฉันได้กำหนดไว้fooแล้ว แต่ยังคงมีการประเมินส่วนอื่น ๆ ทดสอบด้วย EJS 2.3.4 แก้ไข: ใช้localsแทนthisผลงาน
X_Trust

8

ฉันเจอปัญหาเดียวกันกับการใช้ node.js กับพังพอน / express / ejs เมื่อสร้างความสัมพันธ์ระหว่าง 2 คอลเลกชันร่วมกับการเติมข้อมูลของพังพอน () ในกรณีนี้มีผู้ดูแลระบบ user_id แต่เกี่ยวข้องกับผู้ใช้ที่ไม่อยู่ไกลกัน _id
ไม่พบสาเหตุ:

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

ล้มเหลวด้วย "Cannot read property 'name' of null" จากนั้นฉันสังเกตเห็นว่าฉันจำเป็นต้องทำการตรวจสอบดังนี้:

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

ฉันต้องการตรวจสอบ "คอนเทนเนอร์" ของ "ชื่อ" จึงได้ผล!
หลังจากนั้นก็ใช้งานได้เหมือนเดิม:

if ( !users.user_id ) ...  

หวังว่าจะช่วยได้


ไม่อยากจะเชื่อเลยว่ามีเอกสารอย่างเป็นทางการเกี่ยวกับ EJS เพียงไม่กี่ฉบับ ... พวกเขาไม่อัปเดตเอกสารตั้งแต่ปี 2010 !!!
aesede

3

มาที่หน้านี้เพื่อหาคำตอบ แต่ฉันได้พบกับไวยากรณ์อินไลน์ที่สั้นกว่าซึ่งก็คือ:

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

1
สิ่งนี้เป็นอันตรายต่อการใช้งานเนื่องจากหากวัตถุ "ผู้ใช้" ไม่มีคุณสมบัติ "ชื่อ" การแสดงผล ejs จะล้มเหลว
Marko Rochevski


0

สิ่งที่ฉันทำก็แค่ส่งออบเจ็กต์เริ่มต้นที่ฉันเรียกว่า 'data' = '' และส่งต่อไปยังเทมเพลต ejs ทั้งหมดของฉัน หากคุณต้องการส่งผ่านข้อมูลจริงไปยังเทมเพลต ejs ให้เพิ่มเป็นคุณสมบัติของออบเจ็กต์ 'data'

ด้วยวิธีนี้อ็อบเจ็กต์ 'data' จะถูกกำหนดไว้เสมอและคุณจะไม่ได้รับข้อความแสดงข้อผิดพลาดที่ไม่ได้กำหนดแม้ว่าคุณสมบัติของ 'data' จะมีอยู่ในเทมเพลต ejs ของคุณ แต่ไม่ได้อยู่ในเส้นทางการแสดงโหนดของคุณ


0

ฉันมีปัญหาเดียวกันและโชคดีที่ฉันพบว่ายังมีฟังก์ชันลัดวงจรใน JS (ฉันรู้ว่ามีหนึ่งใน Ruby และภาษาอื่น ๆ )

ในฝั่งเซิร์ฟเวอร์ / คอนโทรลเลอร์ของฉัน (มาจาก Node.js / Express):

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

ดูสิ่งที่ฉันทำที่นั่น? && ซึ่งตามหลังตัวแปรที่อาจไม่ได้กำหนด (เช่นrequest.session.survey_resultอ็อบเจ็กต์ซึ่งอาจมีหรือไม่มีข้อมูลฟอร์ม) คือสัญกรณ์ลัดวงจรใน JS สิ่งที่ทำคือประเมินเฉพาะส่วนที่ตามหลัง && หากส่วนทางด้านซ้ายของ && ไม่ได้ระบุไว้ 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


0

คุณสามารถใช้เคล็ดลับนี้:

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

โดยที่ขอบเขตเป็นอ็อบเจ็กต์หลักของผู้ใช้


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

0

ฉันได้คิดวิธีแก้ปัญหาอื่น

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

ฉันหวังว่านี่จะช่วยได้.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.