socket有多香?请自行百度。就我的使用感受来说,http能做的它都能做,http不能做的它也能做。虽说概念上有些绕人,但用起来却是简单直接。
问题
最近在写的项目中有个列表需要不断更新,获取任务状态。原先的实现是前端用定时器去不断请求列表数据获取的。
1
| this.timer = setInterval(() => this.queryTaskList(), 10000);
|
这样做弊端很明显,会有一堆的异步请求。而且因为控制了延迟,所以数据即时性也大大折扣。
解决方法
这种需求,适合用长连接来解决。下面就结合这个具体的问题,来演示下react与flask后台中的实现。
客户端
前后端分离的结构,对前端这边的客户端来说,选择也是有很多的。常见的有:Websocket、socket.io-client 等等。
这里我使用的是socket.io-client
在客户端中的使用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import io from 'socket.io-client';
let socket = io(`ws://127.0.0.1:5000/wstask`);
socket.on('connect', () => { console.log('<= 连接调试服务器成功!'); });
socket.emit('taskInfo', { taskId }, taskInfo => { console.log(taskInfo); });
|
服务端
我的服务端用的是Flask,因为还有很多业务接口用的http服务。需要同时支持Socket + Http 接口。
原有的配置如下:
1 2 3 4 5 6 7 8 9
| from flask import Flask app = Flask(__name__)
@app.route('/') def hello_world(): return 'Hello World'
if __name__ == '__main__': app.run()
|
结合socket实用哦,原有的配置要做些调整。这里我使用的是Flask-SocketIO,改下配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| from flask import Flask, render_template from flask_socketio import SocketIO, emit app = Flask(__name__) app.config['SECRET_KEY'] = 'secret!' socketio = SocketIO(app)
@app.route('/') def hello_world(): return 'Hello World'
@socketio.on('taskInfo',namespace='/wstask') def test_message(message): taskId = message['taskId'] row_data = Task.query.filter_by(id=taskId).first() taskInfo = { 'taskId': message['taskId'], 'status': row_data.status, 'taskLog': row_data.task_log, } return taskInfo
if __name__ == '__main__': socketio.run(app)
|
这里我是直接return了查询结果,其实也可以在服务端去轮询,或者通过emit来触发客户端的数据更新。
1 2 3 4 5 6 7 8 9
| from flask_socketio import emit ... taskInfo = { 'taskId': message['taskId'], 'status': row_data.status, 'taskLog': row_data.task_log, } emit('refreshTaskInfo', taskInfo) ...
|
基础的使用就是这些了,实际过程中,socket主要用于一些实时通信的场景,如:聊天、实时监控等,后面结合使用再补充些吧。