在cli程序中,输入命令得到连续的输出已经是一种进度而美观的页面交互形式,好比下图:

而web程序里也有类似的场景,比如执行一个耗时任务,除了显示出等待图标外,用户还希望把执行的状态及时显示出来.如下图:

这样的界面如何设计呢?我的思路如下:

1.点击按钮后,产生一个新ID,后台运行的线程拿到id后开始运行并及时往数据库中插入记录,同时id被送回到前台;

2.前台拿到id后,开始以此id轮询后台数据表,并将取得的数据显示出来,而取得的数据是后台运行的线程不断写入的;

3.后台线程写入状态1后,即认为任务完成,前台取得此数据后不再轮询并恢复成初始状态.

下面请看具体实现:

前台点击按钮触发Ajax:

    $("#startPhonexCrawl").click(function(){
var taskId=$("#taskIdTxt").val(); if(taskId!="0"){
// 有任务启动则取状态
alert("有任务在执行,请稍等...");
}else{
// 没有任务则启动任务
$.get("/startCrawl/phonex",{},function(data,textStatus){
var taskId=data;
$("#taskIdTxt").val(taskId);
$("#crawlsDiv").html("");
$("#loadingImg").show();
showTask();
});
}
});

后台接到请求后一边启动线程,一边将产生的taskid回传:

    /**
* Start crawl and return crawltask id
* @param crawlName
* @return
*/
@RequestMapping("/startCrawl/{crawlName}")
String startCrawl(@PathVariable("crawlName") String crawlName) {
logger.info("准备启动爬虫:"+crawlName);
long taskId=crawlMapper.getNextTaskId(); BaseCTH cth=null; if("phonex".equalsIgnoreCase(crawlName)) {
cth=new PhonexCTH();
logger.info("Phonex crawl thread is ready.");
}else if("163".equalsIgnoreCase(crawlName) || "Netease".equalsIgnoreCase(crawlName)) {
cth=new NeteaseCTH();
logger.info("Netease crawl thread is ready.");
}else if("snowball".equalsIgnoreCase(crawlName)) {
cth=new SnowballCTH();
logger.info("Snowball crawl thread is ready.");
}else {
logger.warn("Error crawlName:"+crawlName+",so no crawl thread started.");
taskId=0;
} if(cth!=null) {
cth.setTaskId(taskId);
cth.setStockMapper(stockMapper);
cth.setCrawlMapper(crawlMapper);
cth.start();
logger.info("Crawl thread started.");
} return String.valueOf(taskId);
}

从上面的程序也可看出,前台按钮和后台具体爬虫联系的纽带是crawlName,这样处理后,如果要增加新爬虫,只要前台做个链接,然后在分支中与具体爬虫联系上即可.

前台的ajax会在得到返回id后调用showTasks函数:

function showTask(){
var taskId=$("#taskIdTxt").val(); if(taskId!="0"){
$.get("/getCrawlTasks/"+taskId,{},function(data,textStatus){
var message="";
var state="";
var percent=""; for(var i=0,l=data.length;i<l;i++){
message+=data[i].ctime+" "+data[i].msg+"<br/>";
state=data[i].state;
percent=data[i].percent;
} $("#crawlsDiv").html(message);
$("#percentSpan").html(percent+"%"); if(state=="1"){
//alert("爬虫任务"+taskId+"结束");
// 如果任务结束则可启动下一任务
clearTimeout(timerHandler);
$("#taskIdTxt").val("0");
$("#loadingImg").hide();
$("#percentSpan").html("");
}else{
timerHandler=setTimeout("showTask()",3000);
}
});
}
}

showTasks函数会在结束前查看数据状态,如果状态不是1则会以三秒为间隔不断调用自己,从而达到轮询的目的,而轮询取状态的后台函数是

    @RequestMapping("/getCrawlTasks/{taskId}")
List<CrawlTask> getCrawlTasks(@PathVariable("taskId") String taskId) {
logger.info("取得taskId="+taskId+"的爬虫状态:"); return crawlMapper.getCrawlTasks(taskId);
}
    @Select("select id,taskid,state,msg,DATE_FORMAT(ctime,'%Y-%m-%d %T') as ctime,percent from crawltask where taskid=#{taskId} order by id ")
List<CrawlTask> getCrawlTasks(@Param("taskId") String taskId);

这样,每过三秒就会从crawltask表里取得信息显示在页面上.

整套设计里,taskid是前台从db取值和后台线程往数据库写值的联系纽带,有了它的出现,前后台可以在互不知情的情况下良好配合.

当从后台取得状态为1时,下面语句便会发挥作用:

clearTimeout(timerHandler);

timerHandler是启动时的句柄,而一旦clear掉,timeout便不会再起作用,从而结束轮询.

这就是全部设计过程.

--2020年5月6日--

如何让Web程序在点击按钮后出现如执行批处理程序般的效果的更多相关文章

  1. 请写出一段JavaScript代码,要求页面有一个按钮,点击按钮弹出确认框。程序可以判断出用

    请写出一段JavaScript代码,要求页面有一个按钮,点击按钮弹出确认框.程序可以判断出用 户点击的是“确认”还是“取消”. 解答: <HTML> <HEAD> <TI ...

  2. response 后刷新页面,点击按钮后,禁用该按钮

    一,正常的点击按钮后,将其灰显,全部执行完毕再正常显示. this.btnSave.Attributes.Add("onclick", "if (typeof(Page_ ...

  3. TProcedure,TMethod,TNotifyEvent,TWndMethod的区别,并模拟点击按钮后发生的动作

    忽然发现TProcedure和TNotifEvent的区别还挺大的: procedure TForm1.Button2Click(Sender: TObject); begin ShowMessage ...

  4. Java基础 awt Button 点击按钮后在控制台输出文字

        JDK :OpenJDK-11      OS :CentOS 7.6.1810      IDE :Eclipse 2019‑03 typesetting :Markdown   code ...

  5. 微信小程序开发——点击按钮获取用户授权没反应或反应很慢的解决方法

    异常描述: 点击按钮获取用户手机号码,有的时候会出现点击无反应或很久之后才弹出用户授权获取手机号码的弹窗,这种情况下,也会出现点击穿透的问题(详见:微信小程序开发——连续快速点击按钮调用小程序api返 ...

  6. 微信小程序开发——点击按钮退出小程序的实现

    微信小程序官方是没有提供退出的API的,但是在navigator这个组件中,是有退出这个功能的:详情参考官方文档:navigator.示例代码:1 navigator open-type=" ...

  7. 点击按钮后到底发生了什么,Touch,LongClick或者Click?

    按钮点击事件详解 最近一个项目需要给应用初始界面上的动态按钮添加在不同状态的变换效果,如点击(俗一点也可称为按压)后实现背景图的更换或者图标的缩放等效果.由于按钮点击的时间有长有短,所以采用OnTou ...

  8. 如何点击按钮后在加载外部的Js文件

    或许有朋友遇到过,想等自己点击按钮之后才执行某一个js文件,那么,你运气好,看到了我的代码了哈哈, <html> <head> <title></title& ...

  9. 移动端开发H5页面点击按钮后出现闪烁或黑色背景的解决办法

    H5页面在IOS端测试的时候发现,点击按钮会闪动,出现一个黑色的背景一闪而过,影响用户体验.最后通过度娘,找到解决方法: 就是给点击的元素添加一个CSS属性或者全局添加一个css. -webkit-t ...

随机推荐

  1. IDEA的基本使用技巧

    博主在大学里学习的专业是计算机科学与技术,在大三的时候才开始接触 “加瓦”,学习加瓦首先就需要一个运行环境,因为受到了老师们的影响,我第一个编辑JAVA的软件环境便是Eclipse,在学校里学习和使用 ...

  2. Java实现获取一个随机的两位数

    import java.util.Random; //获取一个随机的 两位数public class getrandomdouble { public static void main(String[ ...

  3. CSS 学习第一天

    css的三种引入方式: 1.内嵌:直接在标签中添加style属性 格式:<标签名 style="样式1:样式值1:样式2:样式值2"> 2.内联:在head标签中添加& ...

  4. 商业分析-04行为&业务相关数据指标

    [访问深度]用户对产品的了解程度 [弹出率] 弹出率是基于访问回话的 而不是基于页面的,上图中1 4 6 是属于弹出

  5. QT QJson与QByteArray的转化

    目录 QJsonObject转为QByteArray QByteArray转为QJsonObject 可以将QJsonObject与QByteArray互相转化,以便网络编程时客户端与服务器之间的通信 ...

  6. C#LeetCode刷题之#344-反转字符串​​​​​​​(Reverse String)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3933 访问. 编写一个函数,其作用是将输入的字符串反转过来. 输 ...

  7. java中三大集合框架

    一.List集合 1.List实现的超级父类接口:Collection 存储一组不唯一(允许重复),有序的对象. 2.了解ArrayList类 A):定义的格式:ArrayList<具体类型&g ...

  8. Oracle元数据信息

    一.schema操作 1)查看当前schema select user, sys_context('userenv','current_schema') from dual; 2)切换schema a ...

  9. 完了,这个硬件成精了,它竟然绕过了 CPU...

    我们之前了解过了 Linux 的进程和线程.Linux 内存管理,那么下面我们就来认识一下 Linux 中的 I/O 管理. Linux 系统和其他 UNIX 系统一样,IO 管理比较直接和简洁.所有 ...

  10. html中datalist 是什么??????

    <datalist>标签定义选项列表,与input元素配合使用该元素,来定义input可能值.datdallist及其选项不会被显示出来,它仅仅是合法的输入值列表. <input i ...