Flask动态传递数组至HTML脚本时数据未更新问题
Flask动态数组传前端不同步问题
问题现象
使用Python Flask构建应用时,给ran、azi数组传入静态数据的场景下,HTML脚本的控制台日志可正常获取更新后的数组值;但动态更新数组时,HTML内JavaScript代码中的数组数据无法在控制台同步更新。
静态传值正常场景
该场景下HTML脚本与控制台可成功获取更新数据,后端代码如下:
azi=[0,30,45,60,90] ran=[200,500,800,1000,1500] dopp=[] @app.route('/dashboard.html') def dashboard(): return render_template('dashboard.html',azi=azi,ran=ran,dopp=dopp)
配套HTML脚本代码如下:
<script> var Range = {{ran}}; var Angle = {{azi}}; console.log("Range Array = {{ran}}"); console.log("Azimuth Array = {{azi}}"); </script>
动态更新异常场景
azi、ran、dopp均为全局变量,通过以太网获取实时数据时,Python代码(app.py)中三个数组的值可正常动态更新,但将动态数组值传递至HTML时,脚本内无法获取更新后的值,Chrome控制台中显示为空数组。
以太网数据接收逻辑代码如下:
#azi,ran and dopp are global variables azi=[] ran=[] dopp=[] def ethernet(): print("Initialising....\n") time.sleep(1) s = socket.socket() shost = socket.gethostname() ip = socket.gethostbyname(shost) host = input(str("Enter server address: ")) name = input(str("\nEnter your Command: ")) port = 10 print("\nTrying to connect to ", host, "(", port, ")\n") time.sleep(1) s.connect((host, port)) print("Connected...\n") start_time = time.time() while(1): ran=[] azi=[] dopp=[] if(time.time() - start_time >= 0.5): start_time = time.time() s.send(name.encode()) s_name = s.recv(1024) s_name = s_name.decode() print(s_name, "Received\n") char = "x" indices = [i.start() for i in re.finditer(char, s_name)] a=s_name NumOfCent = (int(a[0 : indices[0]])) MessageType = (int(a[indices[0] + 1 : indices[1]])) DwellNo = (int(a[indices[1] + 1 : indices[2]])) for i in range(2, len(indices) - 3, 3): Range = (int(a[indices[i] + 1 : indices[i + 1]])) Range /= 8.0 ran.append(Range) print(Range) print(ran) Azimuth = (int(a[indices[i + 1] + 1 : indices[i + 2]])) Azimuth /= 8.0 azi.append(Azimuth) print(Azimuth) Doppler = (int(a[indices[i + 2] + 1 : indices[i + 3]])) print(Doppler) print('') dopp.append(Doppler) x = np.multiply(Range,np.sin(Azimuth*3.14/180)) y = np.multiply(Range,np.cos(Azimuth*3.14/180))
问题根因
- Flask的
render_template仅在用户发起页面请求、路由函数被触发的瞬间读取变量值,将值渲染到静态HTML后返回给浏览器。页面加载完成后,后端全局变量的任何更新都不会自动同步到已经加载完成的前端页面。 - 以太网接收逻辑为独立阻塞循环,默认和Flask请求上下文隔离;且循环内部每次都通过
ran=[]、azi=[]、dopp=[]重新赋值,没有提前声明global关键字,修改的是函数内部局部变量,路由函数读取到的全局变量始终为空。 - 以太网逻辑如果直接在主线程运行,会阻塞Flask服务,导致所有请求无法响应。
修复步骤
- 修正全局变量修改逻辑:在
ethernet函数开头声明要操作的全局变量,清空旧数据时用clear()方法而非重新赋值,避免生成局部变量。def ethernet(): global ran, azi, dopp # 省略原有初始化连接逻辑 start_time = time.time() while True: if time.time() - start_time >= 0.5: start_time = time.time() ran.clear() azi.clear() dopp.clear() # 省略原有数据解析、append逻辑 - 新增数据接口,专门返回最新的数组数据,供前端动态拉取:
@app.route('/api/latest_data') def get_latest_data(): return {"ran": ran, "azi": azi, "dopp": dopp} - 修改前端脚本,通过定时器定期拉取最新数据,实现动态更新:
<script> // 初始加载时取默认值 let Range = {{ran|tojson}}; let Angle = {{azi|tojson}}; console.log("初始Range数组:", Range); console.log("初始方位角数组:", Angle); // 每500ms拉取一次最新数据 setInterval(async () => { const resp = await fetch('/api/latest_data'); const latest = await resp.json(); Range = latest.ran; Angle = latest.azi; console.log("更新后Range数组:", Range); console.log("更新后方位角数组:", Angle); // 此处追加数据更新后的页面渲染逻辑 }, 500); </script> - 将以太网接收逻辑放到守护线程中运行,避免阻塞Flask主服务:
import threading # 启动Flask服务前开启以太网线程 eth_thread = threading.Thread(target=ethernet, daemon=True) eth_thread.start() app.run()
内容的提问来源于stack exchange,提问作者Sameer Kumar Shrivastava
相关产品推荐
相关产品推荐

