交互逻辑
- 点击页面的“提交”button,向后台发送数据处理请求;
- 后台处理数据;
- 前端根据后台的处理进度实时更新进度条。
个人愚见:能在前端估计出进度的尽量在前端做伪实时的进度条(像发送文件那种),这才是上策;实在没法估计后台计算时间,又实在是等的久的让人难熬的才这么干,这是下下策。
功能实现
前端
HTML
- Html页面用boostrap的进度条, 进度条由2个div嵌套而成,修改内层div的width可以更新进度,外层div (id=”prog_out”) , 内层div (id=”prog_in”);
- 给button绑定一个onclick方法”submit_query()”。123456<div id="prog_out" class="progress progress-striped active"><div id="prog_in" class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div></div><button type="button" class="btn btn-default" onclick="submit_query()">提交</button>
javascript
- 在onclick方法中设置一个setInterval函数,用于持续请求后台进度,不断更新进度条;
- 向后台发送数据处理请求,当该请求成功返回后结束setInterval函数,并更改进度条样式。
- 由于setInterval和getJSON的回调函数都是异步执行,这里就相当于做了个登记,将任务加入队列。因此submit_query不必等待他俩就可以顺利结束。12345678910111213141516function submit_query(btn){var sitv = setInterval(function(){var prog_url = ... // prog_url指请求进度的url,后面会在django中设置$.getJSON(prog_url, function(res){$('#prog_in').width(res + '%'); // 改变进度条进度,注意这里是内层的div, res是后台返回的进度});}, 1000); // 每1秒查询一次后台进度var this_url = ... // 指当前页面的urlvar yourjson = ...$.getJSON(thisurl, yourjson, function(res){// ...clearInterval(sitv); // 此时请求成功返回结果了,结束对后台进度的查询$('#prog_out').attr("class", "progress progress-bar-success"); // 修改进度条外层div的class, 改为完成形态});}
后端
我这里使用的后端为Django, 使用别的后端思路相当。
2.2.1. 设置两个url, 一个指向处理数据的的函数,另一个指向请求进度的函数
urls.py
|
|
views.py
用全局变量记录处理进度,process_data函数负责具体任务,同时更新后台进度值,show_progress负责将当前进度值返回给前端。当全局变量不被识别的时候使用global关键字。1234567891011num_progress = 0 # 当前的后台进度值(不喜欢全局变量也可以很轻易地换成别的方法代替)def process_data(request): # ... for i in range(12345): # ... 数据处理业务 num_progress = i * 100 / 12345; # 更新后台进度值,因为想返回百分数所以乘100 return JsonResponse(res, safe=False)def show_progress(request): return JsonResponse(num_progress, safe=False)
实现效果
未完成形态
完成形态