Node-redのLambda式(無名関数)で、msg配下の配列の特定の値を使いたい!
ざっくりいうと
過去記事
Node-redのmustacheテンプレート中でeval的な事をしたい時はLambda式を使うと嬉しいです
の続き的な記事で、Lambda式でmsgに含まれる配列についてインデックス指定で参照したい!という事をやる方法です。
Lambda式とは
Lambda式を使ったら、mustacheテンプレートの中で関数が使えます。
例えば、Functionノードで以下のような関数を用意しておきます。
msg._unixTime2ymd = function(){
return function(text, render){
if ( Number(render(text)) === 0 ){
return render("-");
}
var timezoneoffset = -9; // UTC-表示したいタイムゾーン(単位:hour)。JSTなら-9
var d = new Date( Number(render(text)) - (timezoneoffset * 60 - new Date().getTimezoneOffset()) * 60000);
var year = d.getFullYear();
var month = d.getMonth() + 1;
var day = d.getDate();
var hour = ( '0' + d.getHours() ).slice(-2);
var min = ( '0' + d.getMinutes() ).slice(-2);
var sec = ( '0' + d.getSeconds() ).slice(-2);
var D = new Date();
var Year = D.getFullYear();
if (year === Year){
return render( month + '/' + day + ' ' + hour + ':' + min + ':' + sec );
}else{
return render( year + '/' + month + '/' + day + ' ' + hour + ':' + min + ':' + sec );
}
}
};
その後に、テンプレートノード中で
{{#_unixTime2ymd}}{{payload}}{{/_unixTime2ymd}}
などを記載し、Injectノードからmsg.payloadにタイムスタンプ(ms)を渡してあげると2019/01/01 00:00:00
のようになるわけです。(今回の関数は、タイムスタンプが年内のものであれば年は省くので、以下のテストでやったときは6/9 21:53:15
みたいになりましたが。)
ソースはこちら
[{"id":"74fd7327.6fcd14","type":"debug","z":"981e150c.5ff1b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":650,"y":480,"wires":[]},{"id":"ca3a908e.21633","type":"template","z":"981e150c.5ff1b","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{#_unixTime2ymd}}{{payload}}{{/_unixTime2ymd}}","output":"str","x":500,"y":480,"wires":[["74fd7327.6fcd14"]]},{"id":"c0189393.576ae8","type":"function","z":"981e150c.5ff1b","name":"set lambda","func":"msg._unixTime2ymd = function(){\n return function(text, render){\n \n if ( Number(render(text)) === 0 ){\n return render(\"-\");\n }\n var timezoneoffset = -9; // UTC-表示したいタイムゾーン(単位:hour)。JSTなら-9\n\n var d = new Date( Number(render(text)) - (timezoneoffset * 60 - new Date().getTimezoneOffset()) * 60000);\n var year = d.getFullYear();\n var month = d.getMonth() + 1;\n var day = d.getDate();\n var hour = ( '0' + d.getHours() ).slice(-2);\n var min = ( '0' + d.getMinutes() ).slice(-2);\n var sec = ( '0' + d.getSeconds() ).slice(-2);\n \n var D = new Date();\n var Year = D.getFullYear();\n \n if (year === Year){\n return render( month + '/' + day + ' ' + hour + ':' + min + ':' + sec );\n }else{\n return render( year + '/' + month + '/' + day + ' ' + hour + ':' + min + ':' + sec );\n }\n \n \n } \n};\n\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":480,"wires":[["ca3a908e.21633"]]},{"id":"d2325d37.276c78","type":"inject","z":"981e150c.5ff1b","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":180,"y":480,"wires":[["c0189393.576ae8"]]}]
今回の本題
そうなると、msgに入っている配列の特定の値なんかも参照したくなっちゃう訳です。
んで、結論から行くと以下のように使うと良いです。
//Functionノードにて
msg._getArrVal = function(){
var arr = msg.arraysample;
return function(text,render){
return render(arr[render(text)]);
}
};
//msg.arraysample
["hoge","fuga","piyo"]
//mustacheテンプレート
{{#_getArrVal}}0{{/_getArrVal}}
//結果
hoge
ソース
[{"id":"d2325d37.276c78","type":"inject","z":"981e150c.5ff1b","name":"inject","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":480,"wires":[["c0189393.576ae8"]]},{"id":"c0189393.576ae8","type":"function","z":"981e150c.5ff1b","name":"set lambda","func":"msg._getArrVal = function(){\n var arr = msg.arraysample;\n return function(text,render){\n return render(arr[render(text)]);\n }\n};\n\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":480,"wires":[["c99b2df1.634268"]]},{"id":"c99b2df1.634268","type":"change","z":"981e150c.5ff1b","name":"set arraysample","rules":[{"t":"set","p":"arraysample","pt":"msg","to":"[\"hoge\",\"fuga\",\"piyo\"]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":480,"wires":[["ca3a908e.21633"]]},{"id":"ca3a908e.21633","type":"template","z":"981e150c.5ff1b","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{#_getArrVal}}0{{/_getArrVal}}","output":"str","x":680,"y":480,"wires":[["74fd7327.6fcd14"]]},{"id":"74fd7327.6fcd14","type":"debug","z":"981e150c.5ff1b","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":830,"y":480,"wires":[]}]
ちなみに、functionの中のfunctionにあるtext
とrender
という変数はおまじないなのでそのまま使う必要があります。{{#hogehoge}}value{{/hogehoge}}
の様にした時にそのvalue
が入ってくるのがtext
ちゃんです。
この
{{#_getArrVal}}0{{/_getArrVal}}
の0の箇所にもちろん変数を持ってこれるので
//Functionノードにて
msg._getArrVal = (略
msg.index = 1;
//msg.arraysample
["hoge","fuga","piyo"]
//mustacheテンプレート
{{#_getArrVal}}{{index}}{{/_getArrVal}}
//結果
fuga
と出来る訳ですね。
そもそもMustacheのLogic-lessテンプレートという考え方にそぐわない気もしなくはないですが、まぁ色々なニーズがあるのでやり方知っておくと便利かと思います。
ちなみに
今回のケースだとmsg.arraysample
は、このMustacheテンプレートが評価されるまではmsgに含まれている必要があります。
つまり、Lambda式を定義した後にmsg.arraysampleを削除したりすると、正しく動きませんのでご注意ください。(値渡しにすれば良いのかな。試してないけど。)
mustacheそのものについては、以下の翻訳記事も見ておくと良いと思います。
mustache記法について簡単にまとめてみた
では。
Author And Source
この問題について(Node-redのLambda式(無名関数)で、msg配下の配列の特定の値を使いたい!), 我々は、より多くの情報をここで見つけました https://qiita.com/kouichirou/items/7cd737855e2a6407b807著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .