Apa cara yang tepat untuk memeriksa keberadaan variabel dalam template EJS (menggunakan ExpressJS)?

121

Di halaman github EJS, hanya ada satu contoh sederhana: https://github.com/visionmedia/ejs

Contoh

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

Ini sepertinya memeriksa keberadaan variabel bernama pengguna, dan jika ada, lakukan beberapa hal. Duh kan?

Pertanyaan saya adalah, mengapa di dunia ini Node akan melempar ReferenceError jika variabel pengguna tidak ada? Ini membuat contoh di atas tidak berguna. Apa cara yang tepat untuk memeriksa keberadaan variabel? Apakah saya diharapkan untuk menggunakan mekanisme coba / tangkap dan mengambil ReferenceError itu?

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)

Saya memahami bahwa saya dapat membuat kesalahan ini hilang hanya dengan menambahkan variabel lokal "pengguna" di kode server saya, tetapi intinya di sini adalah bahwa saya ingin memeriksa keberadaan variabel tersebut pada waktu proses menggunakan if / else Anda setiap hari pola tipe nullcheck. Pengecualian untuk variabel yang tidak ada tampaknya konyol bagi saya.

Aashay Desai
sumber

Jawaban:

149

Dengan cara yang sama Anda akan melakukannya dengan apa pun di js, typeof foo == 'undefined'atau karena "penduduk setempat" adalah nama objek yang berisi mereka, Anda dapat melakukannya if (locals.foo). Ini hanya js: p mentah

tjholowaychuk
sumber
3
Saya mulai bertanya-tanya apakah saya punya masalah yang lebih besar di tangan saya. Ini melontarkan Reference Error juga: <% alert ('test'); %>
Aashay Desai
1
@Aashay alertadalah bagian dari objek browser window, dan tidak tersedia di node.js. Alternatifnya adalah console.log, meskipun saya tidak tahu apakah itu tersedia dalam template ejs kecuali Anda meneruskannya melalui locals.
Zikes
2
@Zikes Dalam hal ini saya mencari EJS secara khusus, jadi ada di halaman browser. Tapi, seperti yang dikatakan TJ, typeof foo == 'undefined' berfungsi. Saya belajar bahwa saya juga dapat menambahkan sederhana !! foo jika foo telah didefinisikan tetapi kosong atau nol.
Aashay Desai
21
Apakah ada singkatan untuk ini? Mengapa EJS tidak hanya menghormati kasus if (foo)?
mattdlockyer
5
if (locals.user){ }FTW
s2t2
26

Coba persiapkan variabel dengan locals

Contoh: if(locals.user){}

spencer.sm
sumber
23
<% if (locals.user) { %>

 // Your logic goes here 

<% } %>
Anirudh
sumber
13

Anda dapat membuat view helper yang memeriksa "obj === void 0", yang ini untuk 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;
}

Kemudian gunakan dalam tampilan seperti

<%- get('deep.nested.non.existent.value') %>  //returns: null
<%- get('deep.nested.non.existent.value', "default value") %> //returns: default value
Paulius Uza
sumber
3
tidak yakin mengapa ini diturunkan, menurut saya agak elegan.
joseym
Apa perbedaan antara <%=dan <%-?
NobleUplift
2
@NobleUplift Sesuai dengan dokumentasi , di bawah "Tag": <%=HTML mengesampingkan nilai terlebih dahulu; <%-mengeluarkan nilai yang tidak lolos. Jadi <b>akan menjadi tag tebal saat menggunakan <%-, tetapi cukup teks "<b>" saat menggunakan<%=
Matheus Avellar
Terima kasih! Saya tidak tahu <% - bahkan tag yang valid.
NobleUplift
13

Untuk memeriksa apakah pengguna sudah ditentukan, Anda perlu melakukan itu:

<% if (this.user) { %>
   here, user is defined
<% } %>
HenioJR
sumber
3
Ini tidak bekerja di perpustakaan EJS terbaru (1.0.0). Meskipun Javascript valid, EJS akan menolak untuk bertindak seperti yang diharapkan.
Axoren
5
Tidak bekerja untuk saya. Meski sudah saya definisikan foo, klausul else masih dievaluasi. Diuji dengan EJS 2.3.4 EDIT: menggunakan localsdi tempat thiskerja
X_Trust
8

Saya telah menemukan masalah yang sama menggunakan node.js dengan mongoose / express / ejs saat membuat hubungan antara 2 koleksi bersama dengan mongoose's populate (), dalam hal ini admins.user_id ada tetapi terkait dengan users._id yang tidak ada.
Jadi, tidak dapat menemukan alasannya:

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

gagal dengan "Tidak dapat membaca properti 'nama' dari null" Kemudian saya perhatikan bahwa saya perlu melakukan pemeriksaan seperti ini:

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

Saya perlu memeriksa "wadah" dari 'nama', jadi itu berhasil!
Setelah itu, ini bekerja sama:

if ( !users.user_id ) ...  

Semoga membantu.

aesede
sumber
Bagaimanapun, tidak percaya ada begitu sedikit dokumentasi resmi di EJS ... mereka tidak memperbarui dokumentasi mereka sejak 2010 !!!
aesede
3

Datang ke halaman ini untuk sebuah jawaban tetapi saya datang dengan sintaks sebaris yang lebih pendek untuk itu yaitu:

 <h2><%= user.name ? property.escrow.emailAddress : '' %></h2>
Adam Boostani
sumber
1
Ini berbahaya untuk digunakan, karena jika objek 'user' tidak memiliki properti 'name', rendering ejs akan gagal.
Marko Rochevski
1

Untuk ifpernyataan Anda, Anda perlu menggunakan typeof:

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

<% } %>
Fabien Thetis
sumber
0

Apa yang saya lakukan hanyalah meneruskan objek default yang saya sebut 'data' = '' dan meneruskannya ke semua template ejs saya. Jika Anda perlu meneruskan data nyata ke template ejs, tambahkan sebagai properti objek 'data'.

Dengan cara ini, objek 'data' selalu didefinisikan dan Anda tidak pernah mendapatkan pesan kesalahan yang tidak ditentukan, bahkan jika properti 'data' ada di template ejs Anda tetapi tidak di rute ekspres node Anda.

Robert Brax
sumber
0

Saya memiliki masalah yang sama, dan untungnya, saya menemukan bahwa ada juga fungsi sirkuit pendek di JS (saya tahu ada satu di Ruby dan beberapa bahasa lain).

Di sisi server / pengontrol saya (ini dari Node.js / Express):

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

Lihat apa yang saya lakukan di sana? && yang mengikuti setelah variabel yang mungkin tidak terdefinisi (yaitu request.session.survey_resultobjek, yang mungkin memiliki atau tidak memiliki data bentuk) adalah notasi hubung singkat di JS. Yang dilakukannya hanyalah mengevaluasi bagian yang mengikuti && jika bagian di sebelah kiri && TIDAK belum ditentukan. Itu juga tidak membuang kesalahan ketika bagian kiri IS undefined. Itu hanya mengabaikannya.

Sekarang, di templat saya (ingat bahwa saya meneruskan objek req.session.survey_result_surveyobjek ke view saya sebagai survey_result) dan kemudian saya membuat bidang sebagai:

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

Saya juga menggunakan arus pendek di sana, hanya untuk penyimpanan yang aman.

Ketika saya mencobanya dengan cara yang disarankan sebelumnya, cukup:

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

Kadang-kadang, ia masih mencoba mengevaluasi properti dalam pernyataan IF ... Mungkin seseorang dapat memberikan penjelasan mengapa?

Juga, saya ingin mengoreksi yang undefinedperlu tanpa tanda kutip tunggal, seperti yang saya lihat dilakukan pada contoh sebelumnya. Karena kondisi tidak akan pernah mengevaluasi true, saat Anda membandingkan nilai String 'undefined'dengan tipe data undefined.

Yekatjarina Aljaksandrayna Shu
sumber
0

Anda bisa menggunakan trik ini:

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

dimana ruang lingkup adalah objek induk pengguna

Alex Szücs
sumber
0

jika Anda berencana untuk sering menggunakan objek yang sama, Anda dapat menggunakan fungsi seperti ini:

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

pemakaian:

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

Saya telah menemukan solusi lain.

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

Saya harap ini membantu.

omar
sumber