0%

React + Flask前后端分离框架下Socket的使用

socket有多香?请自行百度。就我的使用感受来说,http能做的它都能做,http不能做的它也能做。虽说概念上有些绕人,但用起来却是简单直接。

问题

最近在写的项目中有个列表需要不断更新,获取任务状态。原先的实现是前端用定时器去不断请求列表数据获取的。

1
this.timer = setInterval(() => this.queryTaskList(), 10000);

这样做弊端很明显,会有一堆的异步请求。而且因为控制了延迟,所以数据即时性也大大折扣。

解决方法

这种需求,适合用长连接来解决。下面就结合这个具体的问题,来演示下react与flask后台中的实现。

客户端

前后端分离的结构,对前端这边的客户端来说,选择也是有很多的。常见的有:Websocketsocket.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'

# namespace是自己配置路径,选配的
@socketio.on('taskInfo',namespace='/wstask')
def test_message(message):
taskId = message['taskId']
row_data = Task.query.filter_by(id=taskId).first() # Task用的是SQLAlchemy的ORM Model
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主要用于一些实时通信的场景,如:聊天、实时监控等,后面结合使用再补充些吧。