Node-RED 2.1.xで追加された Link Call ノードをいろいろ試してみた

# Link Call ノードとは

2021/10/21にリリースされたNode-RED 2.1の新しい機能の一つに、[Link Call ノード](https://nodered.org/blog/2021/10/21/version-2-1-released#new-link-call-node) があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/29a0ac16-130a-3c77-bdc5-91a764b3d63c.png)

以下、[公式Blogの投稿](https://nodered.org/blog/2021/10/21/version-2-1-released) の翻訳を引用：

>新しいLink Call ノードをLink in/outノードと一緒につかって、サブルーチンのようなフローを作成できます。
Link-inノードで始まり、新しい「link callノードへ返却」モードになっているLink-outノードで終わるフローがある場合（別のアイコン表示になります）、Link Callノードはフローに値を渡して実行し、結果を呼び出し元のフローに戻すことができます。
サブフローを使用する代わりに、これは複数の場所で再利用したい小さなユーティリティフローを作成するのに最適です。

なるほど、GOTOじゃなくてGOSUBなわけですね。（たとえが古い）
ということで、早速試してみましょう。

（なお、以下の検証は、2021/12/9現在最新のNode-RED 2.1.4を用いて行っています）

# Link-outノードの「モード」

Node-REDの2.1のLink-outノードでは、プロパティ内で新しく「モード」設定ができるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/009b445f-4b50-6070-2588-f21cb9d2c7a4.png)

モードを「link callノードへ返却」に設定すると、アイコンが変わります。

「接続された全てのlinkノードへ送信」に設定した場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/4f9c5e86-f818-27a0-bf0e-1e2a093db3b0.png)
矢印が水平にくる感じですが、「link callノードへ返却」に設定した場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/b1e28fc4-3fa2-3064-9532-ac8110c59af9.png)
となり、矢印が左下になってて「戻る」イメージになります。
また、このモードにすると、hoover表示が「link return」に変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/27d0a65f-f2c7-26ac-8350-233000a93134.png)


「link callノードへ返却」に設定したLink-outノードは、出力ポートがなくなり、別のLink-inノードに接続することができなくなります。

なので、「link callノードへ返却」に設定した場合、これまでのLink-in/outノードとは使い方が逆になるイメージです。これまでの使い方は、Link-outからLink-inに移動するイメージでしたが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/c2ecf8c1-c6a5-3fbc-ecae-c5b2d6eda09e.png)

Link Callノードを使う場合は、Link-inから処理を書いて、Link-outで元のフローに戻す感じになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/6037caca-25dc-a991-bce5-2a1255e401ba.png)

これまでと同様、Link-inノードに名前を付けてないとどのLink-inを呼び出すかが分かりにくくなりますので、Link-inノードには名前を付けておくようにしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/b2cb5d6a-787e-1351-b4ab-6332a9ebf5fc.png)

（モードで設定するんじゃなくて、別の「Link-returnノード」を準備したほうが分かりやすかったんじゃないかなあ）

# Link Callノードの設定

Link Callでどのフローを呼び出すかの設定は、Link Callノードのプロパティで設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/0bf08d52-5c50-456a-3d2a-ef6831f22223.png)
これまでのLink-outノードと同様、接続するLink-inノードを選択しますが、Link-outノードと違い、ラジオボタンになっており、呼び出すリンクは１つのみ選択できます。上の画像のようにどれも選択していない状態では、msgが届いても呼び出しがされない状態になりますので、必ず１つは設定しておきましょう。（選択するとLink Callノードのラベルに設定されます）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/d41e0233-61d0-5b92-b8a6-4a83302b019b.png)

なお、呼び出されるほうは１つしか設定できませんが、複数のLink Callノードから同じLink-inノードを呼び出すことが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/2fa88492-de04-6a85-7574-f16bd7afa898.png)
戻る場合は、呼び出されたLink Callノードに戻りますので、Link-outノード側で戻る先を指定する必要はありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/b4ba2606-3b10-898a-70e5-c4c5e99b4082.png)

これにより、再利用したい共通処理を書いたフローロジックを、複数個所から呼び出すことができるようになります。

（まあ、でも、それだったらサブフローでいいんじゃ？）

# Link Callノードのタイムアウト設定
Link Callノードには、サブフローにない機能として「タイムアウト」設定があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/28ddd1aa-a396-8f6c-accb-50b312daf6a0.png)

タイムアウトを設定することで、設定した秒数以内にLink-outノードからの戻りがなければ、エラーを発生させることができます。
サンプルとして、delayノードで遅延を入れて、タイムアウトの動きを確認してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/a1477867-b600-4bda-5c9a-8b5278c98988.png)

13:33:16にInjectを実行してみると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/90f73dc3-a67f-052b-0a95-b781f1af42eb.png)

13:33:19でタイムアウトが出力されています。ただその後、13:33:21に処理が戻ってきて、それは受信してデバッグノードに出力されていますので、タイムアウトしたmsgオブジェクトが捨てられるわけではないので、注意が必要です。

# サブルーチンの入れ子
Link Callのプロパティで適切に呼び出すLink-inノードを設定することにより、サブルーチン処理を入れ子にすることも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/dabc9ee8-f960-dd14-c912-5a3e13fbaf86.png)

Link Callされた際には、戻り先を永続化するために、msgオブジェクトの中に「_linkSource」というarrayが生成され、その中に呼び出されたnodeのidなどが保存されるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/b40616a5-fec3-c324-8fd2-a5f09a001cdb.png)

# サブルーチンのグループ化
Link Callノードから呼び出されるサブルーチンをグループ化することにより、同じFlowEditor内で一覧でき、背景色等設定することでフローが見やすくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/16736957-1fcd-81ca-628e-38a0dc416f24.png)


またグループの環境変数（同じく[Node-RED 2.1.xの新機能](https://nodered.org/blog/2021/10/21/version-2-1-released#flowgroup-level-environment-variables) ）を使うことにより、サブルーチンの中だけで参照できる変数を定義できるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/0f87f401-a5fa-863b-4dd8-f2aaaf47db0c.png)

なお、グループに対する環境変数の定義については、開発者の西山さんが
[Node-RED2.1の新機能: フローおよびグループに対する環境変数の定義](https://qiita.com/HiroyasuNishiyama/items/ca6a255760e40b247187)
で、紹介されていますので、参考にしてください。

# まとめ
Node-RED 2.1.xで追加されたLink Callノードを詳しく調べてみました。
Link Callノードをつかったサブルーチンは、サブフローをつかったサブルーチンより、編集や参照がしやすくていいんじゃないでしょうか。

- 大規模な処理を隠蔽して管理したいならサブフロー
- ちょっとした処理を共通化するなら、Link Call

という風な使い分けになるかと思います。本記事がみなさんのNode-REDライフの参考になれば幸いです。