一、目录
1. 实验目的
- 掌握 node-red 中的 context、global 作用域
- 掌握 flow 作用域以及使用 flow 保存变量的值
- 掌握 global 作用域以及使用 flow 保存变量的值
- 掌握函数控件的其他功能
2. 实验步骤
2.1 实验 1:使用 context 实现计数器
- 在之前的流中,我们总是在执行函数节点时新建一个变量。函数节点执行完毕以后,这个变量的值就会丢失,没有办法保存。如果需要保存一个变量的值该如何操作?
- 可以借助 context 对象。它可以理解为上下文,或者语境,用于保存内存中的数据,这个数据可以持续保存到下一个消息到来。Context 可用于保存索引,计数或者消息中的数据。
-
拖入 inject 节点与 debug 节点。拖入一个函数节点,进行如下设置:
-
节点部署如下:
- context 相关 API:
context.get ( . . ) : 获 取 一 个 节 点 范 围 内 的 上 下 文 属 性
context.s e t ( . . ) : 设 置 一 个 节 点 范 围 内 的 上 下 文 属 性
context.keys ( . . ) : 返 回 所 有 节 点 范 围 上 下 文 属 性 键 的 列 表
context.flow : 同 flow
context.global : 同 global
实现
1.拖入 inject 节点、函数节点、 debug 节点,并连接
2.设置inject 节点
3.设置函数节点代码
var count = context.get('count')||0;
//如果count不存在就初始化为0,已存在则获取count的值
count += 1;
context.set('count', count);
//执行完+1操作以后保存count的值
msg.payload = count;
return msg;
4.部署查看效果
2.2 实验 2:使用 flow 在不同节点之间传递参数
- 在上面的实验中,函数节点计数器实现了用’count’来保存数据的方法,但是这个’count’里边的内容,是不能被别的节点使用的。(有兴趣的同学可以验证一下)
- 可以使用 flow 来让一个流程内的节点都能够获得共享
-
在上一个实验的基础上,添加第二个函数节点,修改第一个节点使用 flow 来保存 count 变量,在第二个函数节点从 flow 节点取出 count 的值,并显示在第二个 debug 节点上节点部署如下:
-
第一个计数器如下:
-
第二个计数器如下:
实现
1.按照上图,拖入节点,并连接
2.设置第一个计数器代码,如下:
var count = context.get('count') ||0;
//如果count不存在就初始化为0,已存在则获取count的值
count += 1;
context.set('count', count);
//执行完+1操作以后保存count的值
flow.set('flowSave', count);
//设 置一个flowSave,来保存变量count的值
msg.payload = count;
return msg;
3.设置第二个计数器代码,如下:
var count = flow.get('flowSave') | 0;
//如果count不存在就初始化为0,已存在则获取count的值
msg.payload = count;
return msg;
4.部署,查看效果
2.3 实验 3:使用 flow 实现计时器
- 使用 flow 的属性在不同的节点之间传递参数,这个功能十分有用。接下来尝试使用 flow 实现一个节点执行时间的计数器。在 JS 中,可以使用 Data 对象的 getTime 方法获取从 1970 年 1 月 1 日至今的毫秒数。跟时间戳得到的数据类似。在开始节点和结束节点分别获取时间,两个值的差就是这两个节点之间所用的时间了。另外,需要一个延时节点来放在两个计时节点之间。在功能控件里恰好有一个名为“delay”的控件满足要求。它可以控制消息通过自己的时间或者限制它的传递速度。我们会使用它的随机延时的功能。
-
按下图部署节点,包括 inject 节点、两个函数节点、一个 delay 节点、一个 debug 节点;
-
第一个函数节点获取当前时间,并保存到 flow 里
-
delay 节点设置为随机延时 1 到 5 秒
-
第二个函数节点计算出实际延时时间 = 当前时间-starttime
- 部署、运行,并查看延时效果
实现
1.按上图部署节点,包括 inject 节点、两个函数节点、一个 delay 节点、一个 debug 节点,并连接起来,如下图
2.设置第一个函数节点获取当前时间,并保存到 flow 里
//使用data对象的getTime方法获取开始时间,
//并存到'startTime'里
flow.set('stratTime', new Date().getTime());
return msg;
3.设置delay 节点为随机延时 1 到 5 秒
4.设置第二个函数节点计算出实际延时时间 = 当前时间-starttime
var currentTime = new Date().getTime();
//获取当前时间
var stratTime = flow.get('stratTime', stratTime);
//用flow.get获取之间节点储存的开始时间
var timeElapsed = (currentTime - stratTime) / 1000;
//计算时间差并从毫秒转换为秒
msg.payload = "逝去的时间是: " + timeElapsed + "s";
return msg;
5.部署,并查看效果
2.4 实验 4:使用 global 保存变量的值
- 全局变量名为 global,它与 flow 功能类似,但是作用域比 flow 大,并且,即便重新部署,global 储存的值也不会丢失。以下是 global 的 API:
global.get ( . . ) : 获 取 全 局 范 围 的 上 下 文 属 性
global.set ( . . ) : 设 置 全 局 范 围 的 上 下 文 属 性
global.keys ( . . ) : 返 回 所 有 全 局 作 用 域 上 下 文 属 性 键 的 列 表
- 将“实验 3”中的 flow 变量替换成 global,部署运行,查看效果
全部代码
[
{
"id": "92abc220b57377fb",
"type": "tab",
"label": "流程 4",
"disabled": false,
"info": "",
"env": []
},
{
"id": "f23191092f3bbbb5",
"type": "debug",
"z": "92abc220b57377fb",
"name": "debug 20",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 360,
"y": 60,
"wires": []
},
{
"id": "b862b85fd415b52c",
"type": "function",
"z": "92abc220b57377fb",
"name": "function 8",
"func": "var count = context.get('count')||0;\n//如果count不存在就初始化为0,已存在则获取count的值\ncount += 1;\ncontext.set('count', count);\n//执行完+1操作以后保存count的值\nmsg.payload = count;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 220,
"y": 60,
"wires": [
[
"f23191092f3bbbb5"
]
]
},
{
"id": "676d24f7cce7c90f",
"type": "inject",
"z": "92abc220b57377fb",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "num",
"x": 90,
"y": 60,
"wires": [
[
"b862b85fd415b52c"
]
]
},
{
"id": "01e507b9115d4079",
"type": "inject",
"z": "92abc220b57377fb",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "num",
"x": 70,
"y": 160,
"wires": [
[
"e0b92e5c517d95c4"
]
]
},
{
"id": "e0b92e5c517d95c4",
"type": "function",
"z": "92abc220b57377fb",
"name": "function 9",
"func": "var count = context.get('count') ||0;\n//如果count不存在就初始化为0,已存在则获取count的值\ncount += 1;\ncontext.set('count', count);\n//执行完+1操作以后保存count的值\nflow.set('flowSave', count);\n//设 置一个flowSave,来保存变量count的值\nmsg.payload = count;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 220,
"y": 160,
"wires": [
[
"f27c3e10429365e0",
"70ec09a3352dc75f"
]
]
},
{
"id": "70ec09a3352dc75f",
"type": "function",
"z": "92abc220b57377fb",
"name": "function 10",
"func": "var count = flow.get('flowSave') | 0;\n//如果count不存在就初始化为0,已存在则获取count的值\nmsg.payload = count;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 290,
"y": 280,
"wires": [
[
"0827b39eceb3a7c8"
]
]
},
{
"id": "f27c3e10429365e0",
"type": "debug",
"z": "92abc220b57377fb",
"name": "debug 21",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 520,
"y": 140,
"wires": []
},
{
"id": "0827b39eceb3a7c8",
"type": "debug",
"z": "92abc220b57377fb",
"name": "debug 22",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 560,
"y": 240,
"wires": []
},
{
"id": "3220d281150bef58",
"type": "inject",
"z": "92abc220b57377fb",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 110,
"y": 360,
"wires": [
[
"a949395b4102919a"
]
]
},
{
"id": "a949395b4102919a",
"type": "function",
"z": "92abc220b57377fb",
"name": "function 11",
"func": "//使用data对象的getTime方法获取开始时间,\n//并存到'startTime'里\nflow.set('stratTime', new Date().getTime());\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 130,
"y": 440,
"wires": [
[
"b822a973048a9b79"
]
]
},
{
"id": "b822a973048a9b79",
"type": "delay",
"z": "92abc220b57377fb",
"name": "",
"pauseType": "random",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 130,
"y": 520,
"wires": [
[
"0171853049bd6aed"
]
]
},
{
"id": "0171853049bd6aed",
"type": "function",
"z": "92abc220b57377fb",
"name": "function 12",
"func": "var currentTime = new Date().getTime();\n//获取当前时间\nvar stratTime = flow.get('stratTime', stratTime);\n//用flow.get获取之间节点储存的开始时间\nvar timeElapsed = (currentTime - stratTime) / 1000;\n//计算时间差并从毫秒转换为秒\nmsg.payload = \"逝去的时间是: \" + timeElapsed + \"s\";\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 150,
"y": 600,
"wires": [
[
"5a9b7f2d694be2af"
]
]
},
{
"id": "5a9b7f2d694be2af",
"type": "debug",
"z": "92abc220b57377fb",
"name": "debug 23",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 140,
"y": 680,
"wires": []
}
]