利用DWF的服务器端脚本可以在后端(服务器)运行自己的程序,此时DWF的前端和后端之间没有任何方式进行联系,消息订阅控件可以帮助前后端脚本之间建立起实时联系,从而有助于帮助用户通过脚本对后端发生的情况作出相应的处理,使用消息订阅控件的场合包括:
下面是订阅控件的一个例子:
图-订阅控件示例
在表单编辑工具里,消息订阅控件位于多对象控件分类中,拖入以后会在建模工具的画布区显示一个占位符,在应用端消息订阅控件不会显示任何效果,仅负责向服务器端发送和从服务器端接受消息的任务。
图-消息订阅控件的使用
虽然DWF中的大部分控件均具有动态响应开关,会在对象发生变化的时候自动更新其展示方式,但是消息订阅控件和控件自身动态响应开关的作用存在下面的两项不同:
第一、消息订阅控件允许在对象增删改的时候得到通知进行更加个性化的前端刷新操作
第二、对于超出增删改以外的自定义的后端逻辑,使用消息订阅控件可以允许用户在后端脚本中建立个性化的通讯,从而实现个性化的前端动态响应。
下面,介绍消息订阅控件的基本概念和用法。
当消息订阅控件被拖入表单中以后,有两种针对服务器端发生事件的订阅模式:
图-消息订阅的类型设置界面
默认情况下,订阅控件所在表单启动的时候会自动启动消息订阅,如果选择手动启动消息订阅,前端脚本可以使用如下的函数开始或停止订阅:
var addin = this.getAddinById("控件ID");
在开启订阅的双向通讯通道之后,消息订阅控件不仅能帮助前端感知后端的变化,脚本的开发者也可以利用订阅控件在前后端发送或者接受消息,从而实现快速通讯。
在前端脚本中,可以使用this.getAddinById()获得订阅插件的引用,之后使用sendMsg(obj)可以向正在运行的后端发送消息。
前端发送消息代码示例:
var addin = this.getAddinById("控件代号"); var obj = { }; addin.sendMsg(obj); |
后端在执行的脚本里通过this.websocket.socketId判断连接是否有效,利用this.websocket.getMsg()得到最近一次发送的消息。
后端接受消息代码示例:
if (this.websocket.socketId){ var msg = this.webSocket.getMsg(); this.logger.info(msg.toString()); } |
同样的道理,后端向前端发送消息的过程可以利用this.websocket.sendMsg(obj)实现,向前端的消息发送,此时会触发订阅控件的阶段消息到达事件。
后端发送消毒的代码示例:
if (this.websocket.socketId) { var msg = {}; this.websocket.sendMsg(msg); } |
前端接受消息的代码示例:
var addin = this.getAddinById("控件ID"); var msg = addin.getMsg(); console.log(msg); |
开始订阅以后,如何在前端得到后端事件发生的消息并进行处理呢?在消息订阅控件自身控件事件有两种内置的前端事件一个是结束消息到达事件,一个是阶段消息到达事件。
在事件的代码中获取消息的方法是通过
var addin = this.getAddinById("控件ID");
在类事件订阅模式中:
var addin = this.getAddinById("控件ID"); var msg = addin.getMsg(); console.log(msg); |
在脚本事件订阅模式中:
同样的,在脚本中也可以利用getMsg()得到最近的消息。
在了解了消息订阅控件的用法以后,接下来介绍一个案例,用自定义控件创建一个仪表盘,并且从服务器端收集数据控制前端刷新仪表盘的读数,效果如下所示:
图-利用消息订阅实现实时刷新
实现上述效果的定制方法是:
被定制表单如下所示:
图-被定制的表单
定制好表单以后,实现动态刷新的基本原理是:
第一步:设置启动按钮和结束按钮,调用消息订阅控件启动后端脚本,或者发送停止信息给消息订阅控件通知后端停止采集数据。可以新建两个动作为implement的操作填入以下代码:
启动订阅控件
var addin = this.getAddinById("WatchMessage1"); // WatchMessage1是消息订阅控件的代号 addin.start(); |
停止订阅控件
var addin = this.getAddinById("WatchMessage1"); // WatchMessage1是消息订阅控件的代号 addin.stop(); |
第二步:设置消息订阅控件的后端脚本操作,只要没有收到停止消息,就每隔1.5秒收集速度,油位,水位,转速信息发往前端,在本次案例中上述信息以随机数形式产生,在真实情况下上述信息可以从IoTDB等时间序列数据库中查询。
var Thread = Java.type("java.lang.Thread"); while (this.websocket.socketId) { var msg = this.websocket.getMsg(); if (msg){ var objMsg = { "speed":(Math.random()*100).toFixed(2) - 0, "rpm":(Math.random()*7).toFixed(2) - 0, "oil":(Math.random()*2).toFixed(2) - 0, "water":(Math.random()*2).toFixed(2) - 0 } this.websocket.sendMsg(objMsg); // 向前端发送消息 if (msg1.data.contains("stop")) { this.res = "停止读数" break; } } Thread.sleep(1500); } this.logger.info("运行结束"); |
第三步:前端自定义控件按照2秒的周期刷新,每次刷新的时候从消息订阅控件中读取最新后端消息,然后设置刷新自身,下面是简略的代码:
option = { ... } let that = this; setInterval(function (){ var addin = that.getAddinById("WatchMessage1"); if (addin){ var msg = addin.getMsg(); if (msg){ option.series[0].data[0].value = msg.data.speed;//speed option.series[1].data[0].value = msg.data.rpm;//rpm option.series[2].data[0].value = msg.data.oil;//oil option.series[3].data[0].value = msg.data.water;//water myChart.setOption(option, true); } } },2000); |
最后,启动的效果如下所示:
本章主要介绍了订阅控件的使用方法,消息订阅控件可以在后端脚本和前端界面之间建立起一个通道,使得前端能及时了解后端的运行状态,订阅控件提供了下面的支持:
最后,结合自定义可视化事件,实现了一个仪表盘的案例。