Node-REDの基本的動作を理解していなかったNode-RED初心者のメモです。
問題となった処理
以下のフローは、No.2のfunctionノードを起点に繰り返し処理を終端No.7まで順番に行われることを期待して作りました。ですが、結果は全く違ったものでした。
[No.2の処理]
// test: array data
let data = [];
for (let index = 0; index < 10; index++) {
data.push(index);
}
// node.send: array
data.forEach(function (element) {
msg.payload = element;
node.send(msg);
});
期待動作(こうなると思っていた動作)
No.2を起点にNo.3~7の処理を順番に繰り返し処理するはず。
No.7の結果出力は全てOKとなるはず。
1. inject: 処理開始
2. function: 繰り返し処理(10回 output[{payload:0},{payload:1}, ...,{payload:9}])
3. change: flow.temp = payload(0)
4. change: result = flow.temp(0);
5. switch: compare result(0) === payload(0)
6. change: OK/NG判定
7. debug: 結果出力(OK)
3. change: flow.temp = payload(0)
4. change: result = flow.temp(0);
5. switch: compare result(0) === payload(0)
6. change: OK/NG判定
7. debug: 結果出力(OK)
… ※繰り返し
実際の動作
「No.3 -> 4 -> 5 -> 6 -> 7 -> 3 -> 省略
」と進まず「No.3,3,…,3(10回) -> 4,4,…,4(10回) -> 省略
」と**ノード単位に繰り返し処理が実行
**されていました。
1. inject: 処理開始
2. function: 繰り返し処理(10回 output[{payload:0},{payload:1}, ...,{payload:9}])
3. change: flow.temp = payload(0)
3. change: flow.temp = payload(1)
~~省略~~
3. change: flow.temp = payload(9) **※注目箇所;No.3.changeノードを10回繰り返すため、flow.tempに(9)が設定される。**
4. change: result = flow.temp(9);
4. change: result = flow.temp(9);
~~省略~~
4. change: result = flow.temp(9); **※注目箇所:No.4.changeノードを10回繰り返すが、全てresultに(9)が設定される。**
5. switch: compare result(9) === payload(0)
5. switch: compare result(9) === payload(1)
~~省略~~
5. switch: compare result(9) === payload(9) **※注目箇所:最終データ以外は全て偽となる。**
6. change: OK/NG判定
6. change: OK/NG判定
~~省略~~
6. change: OK/NG判定)
7. debug: 結果出力(NG)
7. debug: 結果出力(NG)
~~省略~~
7. debug: 結果出力(OK)
[処理結果]
NG
NG
NG
NG
NG
NG
NG
NG
NG
OK
期待通り動作させるためのフロー(2021/08/06:修正)
下記フローが良い方法なのか分かりませんが、期待通りに動作させることが出来ました。
2021/08/06:修正:ループ処理に再要求された場合に正しく動作しないのを修正しました。
このフローには、npmモジュールの"node-red-contrib-simple-message-queue"
を使用しています。
実際に使用する場合は、デッドロックしないよう例外処理やタイムアウト処理を実装する必要があります。
1. inject: 処理開始
2. function: 繰り返し処理(10回 output[{payload:0},{payload:1}, ...,{payload:9}])
3. simple-queue: option設定"Bypass first message?"で初回キューのみ取り出し。
4. change: flow.temp = payload(0)
5. change: result = flow.temp(0);
6. switch: compare result(0) === payload(0)
7. change: OK/NG判定
8. debug: 結果出力(OK)
9. change: trigger = "1"
10. link-out
11. link-in
3. simple-queue: trigger(1)要求でキューを1個つ取り出す。
参考フロー(2021/08/06:修正)
2021/08/06:修正:ループ処理に再要求された場合に正しく動作しないのを修正しました。