RestAPI与WebSockets结合:同时实现传统请求响应与实时数据获取
实现Flask传统API与实时数据推送共存的方案
可以用Flask-SocketIO扩展来实现,它能让你的Flask应用同时处理HTTP请求(传统REST API)和WebSocket连接(实时数据推送),完全符合你的需求。以下是具体实现步骤:
1. 安装必要依赖
后端需要安装Flask-SocketIO:
pip install flask-socketio python-socketio
前端React需要安装socket.io客户端:
npm install socket.io-client
2. 修改Flask后端代码
保留原有的REST API接口,同时添加WebSocket相关逻辑,优化Tuya API连接复用(避免每次请求重新初始化连接):
from flask import Flask, request from flask_cors import CORS from flask_socketio import SocketIO, emit from tuya_connector import TuyaOpenAPI, TUYA_LOGGER import time from threading import Thread app = Flask(__name__) CORS(app, resources={r"/*": {"origins": "*"}}) # 配置跨域支持WebSocket socketio = SocketIO(app, cors_allowed_origins="*") # 全局初始化Tuya OpenAPI连接,避免每次请求重复初始化 ACCESS_ID = "" ACCESS_KEY = "" API_ENDPOINT = "" openapi = TuyaOpenAPI(API_ENDPOINT, ACCESS_ID, ACCESS_KEY) openapi.connect() # 保留原有的传统REST API接口 @app.get("/api/device/<string:deviceid>") def getdata(deviceid): # 调用Tuya API获取设备信息 response = openapi.get("/v1.0/devices/{}".format(deviceid)) return response # WebSocket连接事件 @socketio.on('connect') def handle_connect(): print('客户端已连接') emit('connected', {'message': 'WebSocket连接成功'}) # 客户端订阅特定设备的实时数据 @socketio.on('subscribe_device') def handle_subscribe(deviceid): def push_realtime_data(): while True: # 定时获取设备数据并推送给客户端 try: response = openapi.get("/v1.0/devices/{}".format(deviceid)) emit('device_realtime_data', {'deviceid': deviceid, 'data': response}) except Exception as e: emit('error', {'message': str(e)}) time.sleep(5) # 每5秒推送一次,可根据需求调整间隔 # 启动线程持续推送数据 Thread(target=push_realtime_data, daemon=True).start() if __name__ == '__main__': socketio.run(app, debug=True)
3. React前端实现
同时保留HTTP请求调用传统API,以及WebSocket接收实时数据:
import { useEffect, useState } from 'react'; import io from 'socket.io-client'; const DevicePage = ({ deviceId }) => { const [staticData, setStaticData] = useState(null); const [realtimeData, setRealtimeData] = useState(null); const socket = io('http://localhost:5000'); // 替换为你的Flask服务地址 // 调用传统REST API获取静态数据 useEffect(() => { const fetchStaticData = async () => { const res = await fetch(`http://localhost:5000/api/device/${deviceId}`); const data = await res.json(); setStaticData(data); }; fetchStaticData(); }, [deviceId]); // 处理WebSocket实时数据 useEffect(() => { // 监听连接成功事件 socket.on('connected', (msg) => { console.log(msg.message); // 订阅当前设备的实时数据 socket.emit('subscribe_device', deviceId); }); // 接收实时设备数据 socket.on('device_realtime_data', (data) => { setRealtimeData(data.data); }); // 监听错误信息 socket.on('error', (err) => { console.error('实时数据推送错误:', err.message); }); // 组件卸载时断开连接 return () => { socket.disconnect(); }; }, [deviceId, socket]); return ( <div> <h2>设备静态信息</h2> <pre>{JSON.stringify(staticData, null, 2)}</pre> <h2>设备实时数据</h2> <pre>{JSON.stringify(realtimeData, null, 2)}</pre> </div> ); }; export default DevicePage;
关键说明
- 连接复用:将Tuya OpenAPI的初始化移到全局,避免每次HTTP请求或WebSocket推送都重新建立连接,提升性能。
- 线程处理:WebSocket推送实时数据时使用守护线程,避免阻塞Flask的事件循环。
- 跨域配置:确保Flask的CORS和SocketIO的跨域配置正确,避免前端连接失败。
内容的提问来源于stack exchange,提问作者user20288092
相关产品推荐
相关产品推荐

