(ExpressJSを使用して)E​​JSテンプレート内の変数の存在を確認する適切な方法は何ですか?


121

EJS githubページには、https//github.com/visionmedia/ejsの簡単な例が1つだけあり ます。

<% 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タイプのパターン。存在しない変数の例外は私にはばかげているようです。

回答:


149

js、、typeof foo == 'undefined'または「ローカル」がそれらを含むオブジェクトの名前であるため、何かを行う場合と同じ方法で、を実行できますif (locals.foo)。それはただのjs:pです。


3
私の手にもっと大きな問題があるのではないかと思い始めています。これも参照エラーをスローします。<%alert( 'test'); %>
Aashay Desai 2011

1
@Aashay alertはブラウザのwindowオブジェクトの一部であり、node.jsでは使用できません。別の方法はconsole.logですが、を介して渡さない限り、ejsテンプレートで使用できるかどうかはわかりませんlocals
Zikes、2011年

2
@Zikesこの場合、私は特にEJSを探しているので、ブラウザーページにあります。しかし、TJが言ったように、typeof foo == 'undefined'は機能します。fooが定義されているがnullまたは空の場合、単純な!! fooも追加できることを学びました。
Aashay Desai 2011

21
これの省略形はありますか?EJSが単純にif(foo)ケースを尊重しないのはなぜですか?
mattdlockyer 2013

5
if (locals.user){ }FTW
s2t2 2016年

26

変数を前に追加してみてください locals

例: if(locals.user){}



13

"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

3
なぜこれが反対票を投じられたのかわからない、私の意見ではかなりエレガントです。
joseym 2015

違いは何である<%=とは<%-
NobleUplift

2
@NobleUplift ドキュメントに従って「タグ」の下:<%=HTMLは最初に値をエスケープします。<%-エスケープされていない値を出力します。したがって<b>、を使用すると太字のタグに<%-なりますが、使用すると単に「<b>」というテキストになります<%=
Matheus Avellar

ありがとうございました!<%-が有効なタグであることさえわかりませんでした。
NobleUplift

13

ユーザーが定義されているかどうかを確認するには、次のようにする必要があります。

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

3
これは、最新のEJSライブラリ(1.0.0)では機能しません。EJSは有効なJavaScriptですが、期待どおりの動作を拒否します。
Axoren 2015

5
私には効きません。を定義しましたがfoo、else句は引き続き評価されます。EJS 2.3.4でテスト済み編集:作品のlocals代わりに使用this
X_Trust

8

mongoose / populate()で2つのコレクション間の関係を作成するときに、mongoose / express / ejsでnode.jsを使用して同じ問題に遭遇しました。この場合、admins.user_idは存在しましたが、存在しないusers._idに関連していました。
だから、理由が見つかりませんでした:

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

「プロパティ 'name'のnullを読み取れません」で失敗しました。次に、次のようなチェックを行う必要があることに気付きました。

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

「名前」の「コンテナ」を確認する必要があったので、うまくいきました!
その後、これは同じように機能しました:

if ( !users.user_id ) ...  

それが役に立てば幸い。


とにかく、EJSの公式ドキュメントがほとんどないので信じられません... 2010年以降、ドキュメントを更新していません!!!
aesede

3

答えを得るためにこのページに来ましたが、私はそれのための短いインライン構文を思いつきました:

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

1
オブジェクト 'user'に 'name'プロパティがない場合、これは危険です。ejsレンダリングは失敗します。
Marko Rochevski、


0

私が行うことは、 'data' = ''と呼ぶデフォルトのオブジェクトを渡して、それをすべてのejsテンプレートに渡すだけです。実際のデータをejsテンプレートに渡す必要がある場合は、それらを「data」オブジェクトのプロパティとして追加します。

このように、「data」オブジェクトが常に定義され、edataテンプレートに「data」のプロパティが存在するがノードの高速ルートには存在しない場合でも、未定義のエラーメッセージが表示されることはありません。


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の短絡表記です。&&の左側の部分が未定義でない場合にのみ、&&に続く部分を評価します。左側の部分がISの場合もエラーをスローしません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.