目录
前言
0. 目录结构
1. Python 后端进度条-交互逻辑
2. Python 后端进度条-前端代码
2.1 download.html
2.2 javascript 代码实现 (主要功能
2.3 Python 后端进度条-后端逻辑代码
3. 注意事项
4. 总结
前言
今天上班时,突然有人在群里问前端如何实时显示后端处理进度的问题,想了想觉得挺有意思,于是网上看看材料,自己简单的实践了一个以做学习记录。0. 目录结构

1. Python 后端进度条-交互逻辑
思路:
1. 点击页面的“展示进度条测试数据”按钮button,向后台发送数据处理请求;
2. 后台处理数据: process_data,做主要的业务逻辑处理(示例仅简单显示循环数);
3. 后台展示数据: show_progress,通过一个接口过去上一步接口设置的公共变量值;
4. 前端根据后台的处理进度实时更新进度条。
此程序 的负载主要集中在前端,所以对后端的负载很小.
2. Python 后端进度条-前端代码
2.1 download.html
Html页面用boostrap的进度条, 进度条由2个div嵌套而成,修改内层div的width可以更新进度
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>进度条</title>
<script src='/static/js/jquery-3.3.1.min.js'></script>
<style>
.progress-div{
background: rgba(0, 0, 0, 0.03);
width: 1000px;
height: 140px;
padding: 60px 20px;
visibility: hidden;
}
.progress{
margin: 0;
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<!--1. 按钮-->
<button class="btn btn-default" type="button">展示进度条测试数据</button>
<button class=‘’btn btn-default‘’ type=‘’button‘’>重新展示
<!--2. 进度条-->
<div class="progress-div">
<div class="progress">
<div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em; width: 2%;">2%
</div>
</div>
</div>
</div>
</body>
2.2 javascript 代码实现 (主要功能)
在这里边可以看到在更新前端界面的时候设置 0.5秒钟去更新后台的数据.这个地方因为测试的数据特别快,在正常的业务中可以根据实际情况设置.
- 首先为按钮button绑定点击事件click
- 在click事件中设置一个setInterval函数,用于持续请求后台进度,不断更新进度条;
- 向后台发送数据处理请求,当该请求成功返回后结束setInterval函数,并更改进度条样式。
由于setInterval和getJSON的回调函数都是异步执行,这里就相当于做了个登记,将任务加入队列。
代码如下:
<script>
// 生成随机uuid(防止多用户请求进度条混乱)
function guid(){
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy/]g, function(c){
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
$(function () {
$('.btn').on('click', function () {
// 生成唯一的uuid
var uuid = guid();
// 设置定时器,隔段时间请求一次数据
var sitv = setInterval(function(){
// prog_url指向请求进度的url,后面会在flask中设置
var prog_url = '/show_progress/' + uuid
$.getJSON(prog_url, function(num_progress){
$('.progress-div').css('visibility', 'visible');
$('.progress-bar').css('width', num_progress.res + '%');
$('.progress-bar').css('background', 'green');
$('.progress-bar').css('text-align', 'center');
$('.progress-bar').text(num_progress.res + '%');
});
}, 500);
// 点击事件第一个请求地址,发送请求,后台业务开始执行
var this_url = '/progress_data/' + uuid
$.getJSON(this_url, function(res){
// 清楚定时器
cleanInterval(sitv);
if(res.res != null){
$('.progress-bar').css('width', '100%');
$('.progress-bar').text('100%');
setTimeout(function(){
alert('下载成功!');
}, 100);
}else{
$('.progress-bar').css('background', 'red');
setTimeout(function(){
alert('失败了!');
}, 1);
}
});
})
})
</script>
2.3 Python 后端进度条-后端逻辑代码
我这里使用的后端为Flask, 使用别的后端思路相当。
manage.py:
from flask import Flask, jsonify, render_template
app = Flask(__name__)
# 存储进度数据
progress_data = {}
@app.route('/')
def index():
'''
展示主页面
'''
return render_template('download.html')
@app.route('/progress_data/<uuid>')
def progress_data(uuid):
'''
通过uuid将数据存入变量progress_data
'''
for i in range(12345666):
num_progress = round(i * 100 / 12345665, 2)
progress_data[uuid] = num_progress
return jsonify({'res': num_progress})
@app.route('/show_progress/<uuid>')
def show_progress(uuid):
'''
前端请求进度的函数
'''
return jsonify({'res': progress_data[uuid]})
if __name__ = '__main__':
app.run(host='127.0.0.1', port=8013, debug=True)
3. 注意事项
- 使用alert是需要注意,会阻塞js主线程,然后才会渲染页面(那些改变css等等语句),或者将alert放入setTimeout中延迟执行。
- 如果同时发起多个请求(1个以上页面不同时间点击button),由于前端请求的是后端设置的全局变量,所以会出现进度条混乱,解决方法就是前端每次请求都带上一个唯一标示的uuid,后端设置公共变量时可以以uuid为键,进度为值。
- 注意在download.html的head标签中引入jquery.js,否则使用$时会报错。
4. 总结
总的思路如下:
当用户点击了展示进度条按钮,前端页面的js代码开始工作,先向后端progress_data发送业务处理请求,同时设置一个定时器,这个定时器会按照一定频率请求后端另外一个接口(show_progress),在后端的show_progress接口中返回了一个公共变量progress_data的值(一个百分比),这个变量的值是由接口progress_data设置进去的,当接口progress_data完成了业务(比例为100%),此时前端调用的接口progress_data才会有返回值,然后根据这个返回值提示用户进度条展示成功与否。
注意:
无论成功失败,计时器一定要记得清除掉;
完整代码下载:progress_demo.zip