我正在尝试在flask中编写一个后端,该后端必须对外部计算机(check1,check2等)执行许多检查。这是一个顺序过程(检查n之后,我们检查n + 1),但是它需要存储“当前状态”。例如,check1包含从外部API轮询资源(每秒卷曲),该API返回计算机的某些日志。
每当后端在检索到的日志中找到“某些字符串”时,后端就必须更新后端的全局状态,将其报告给前端(以刷新布局组件)并跳至下一个状态。
同样,在下一个状态中,后端正在检查其他内容,当找到“另一个字符串”时,更新全局状态,通知前端新状态并跳至下一个状态。
以此类推,这是核心思想。
它只有一条路线(/)。
该Webapp并非用于生产,仅需工作即可,其目的只是演示系统的发展方式(监视示例)。必须广播全局状态,以便任何人去路由/将看到当前状态布局。
我是Web开发的新手,我认为这是一个奇怪的应用程序,没有我想的那么琐碎。
下面,我显示一些代码,表示:
状态0:通过套接字将新状态(数据)传达给前端。不执行任何操作,仅在开始按钮中等待onClick事件。发生这种情况时,跳到状态1。
状态1:通过socketio将新状态(数据)传达到前端。然后,执行一些任务。当任务“成功”将跳到下一个状态2。
无论状态如何,用户都可以在Web UI中更改参数(参数)。我通过底部的socketio条目进行处理。
main.py
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import time, json
global data
data = {'state': '0', 'param': '50', 'disableStart': 'false', 'disableReset': 'true', 'info': 'Waiting to start'}
def state_1():
print("[Server.state_1]: In state 1...checking service")
data['state'] = '1'
data['disableStart'] = 'true'
data['disableReset'] = 'true'
data['info'] = 'Waiting for service is OK'
socketio.emit('refresh', json.dumps(data), broadcast=True)
# Checking if service is OK...
# Below is just a dummy sustitute
counter = 0
while counter < 100:
print("Checking..." + str(counter) + "%")
time.sleep(1)
counter += 1
# When service is OK jump to state_2()
def state_0():
print("[Server.state_0]: In state 0...waiting to start...")
data['state'] = '0'
data['info'] = 'Waiting to start'
socketio.emit('refresh', json.dumps(data), broadcast=True)
# initialize Flask
app = Flask(__name__)
socketio = SocketIO(app)
@app.route('/')
def index():
print("[Server.index]: " + json.dumps(data))
return render_template('index.html')
@socketio.on('connect')
def on_connect():
print("[Server.on_connect]: A new connection!")
print("[Server.on_connect]: " + json.dumps(data))
# In every new refresh or new tab, we need to display current state
emit('refresh', json.dumps(data), broadcast=True)
# Jump to current state
print("[Server.on_connect]: Jump to state " + data['state'])
f_name = "state_" + data['state']
globals()[f_name]()
@socketio.on('start')
def on_start():
print("[Server.on_start]: Clicked on START button! Jump to state 1")
state_1()
@socketio.on('update_slide_param')
def on_update_slide_param(paramVal):
data['param'] = paramVal
# Setting this param to an external machine...
print("[Server.on_update_slide_param]: A new value has been set! Jump to state " + data['state'])
f_name = "state_" + data['state']
globals()[f_name]()
if __name__ == '__main__':
socketio.run(app, debug=True)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Flask SocketIO Test</title>
</head>
<body>
<p>Some sample code to make sure Flask-SocketIO works...</p>
<button onclick="onClickStart()" id="startButton">START</button>
<button onclick="onClickReset()" id="resetButton">RESET</button>
<input onchange="onSetSliderVal()" class="slider" type="range" id="idSlider" min="50" max="300" value="50"/>
<p>Value: <span id="idSliderVal"></span></p>
<script type="text/javascript" charset="utf-8">
var slider = document.getElementById("idSlider");
var output = document.getElementById("idSliderVal");
output.innerHTML = slider.value; // Display the default slider value
// Update the current slider value (each time you drag the slider handle)
slider.oninput = function () {
output.innerHTML = this.value;
}
</script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script type="text/javascript" charset="utf-8">
var socket = io.connect('http://' + document.domain + ':' + location.port);
// verify our websocket connection is established
socket.on('connect', function () {
console.log('Websocket connected!');
});
// onClickStart - emit a message on the 'start' channel to
// launch a new demo with default parameters
function onClickStart() {
console.log('Starting demo...');
socket.emit('start');
};
// onSetSliderVal - emit a message on the 'update_slide_param' channel to
// perform the action and update global 'data'
function onSetSliderVal() {
var paramVal = document.getElementById('idSlider').value;
console.log('Setting a value of ' + paramVal + '...');
socket.emit('update_slide_param', paramVal);
};
socket.on('refresh', function (data) {
var x = JSON.parse(data); // This is the way we can use our dictionary 'data' as a JSON in JS
console.log('[refresh] Frontend has updated info! Now we are in state ' + x.state);
console.log('[refresh] All variables are:'); console.log(x);
document.getElementById('idSlider').value = x.param;
document.getElementById("idSliderVal").innerHTML = x.param;
document.getElementById('startButton').disabled = JSON.parse(x.disableStart); // This is the cleanest way JS converts a "true"/"false" (string) into true/false (boolean)
document.getElementById('resetButton').disabled = JSON.parse(x.disableReset);
});
</script>
</body>
</html>
问题:
如果我在状态0期间刷新,则可以正常工作。在此状态下,我可以更改“参数”,并且在每个打开的浏览器选项卡中都会更新信息。如果我刷新,则更新的“参数”将保持不变。
然后,我按开始按钮,一切都很好(前端状态根据需要进行了更新)。但是,如果刷新选项卡,则会发生两件事:
a。在浏览器开发工具中,套接字中的控制台信息消失了。
b。服务器中的state_1()函数将再次执行,服务器日志中将显示以下内容:
检查中... 2% 检查中... 16% 检查中... 3% 检查中... 17% 正在检查... 4%
...
当然,似乎执行了该函数的新“实例”。
总而言之,很高兴收到一些反馈。您可以使用提供的代码快速测试问题(创建venv,pip3安装flask flask-socketio,创建index.html的模板文件夹,然后仅创建“ python3 main.py”)