在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. Spring JdbcTemplate中关于RowMapper的使用实例

    在spring boot 集成使用jdbctemplate,首先在pom文件中引入相应的依赖 <dependency> <groupId>org.springframework ...

  2. linux7手动添加systemctl启动程序

    1.路径 [root@angrymushrooms01 system]# pwd /usr/lib/systemd/system 2.脚本内容 vim xxx.service ------------ ...

  3. IDEA 非常重要的一些设置项 → 一连串的问题差点让我重新用回 Eclipse !

    开心一刻 建筑行业内,我看过的最凶残笑话(IT行业内好一致!) 上联:一天晚上两个甲方三更半夜四处催图只好周五加班到周六早上七点画好八点传完九点上床睡觉十分痛苦 下联:十点才过九分甲方八个短信七个电话 ...

  4. 思维导图概览SpringCloud

    @ 目录 1.什么是微服务 1.1.架构演进 1.2.微服务架构 1.3.微服务解决方案 2.SpringCloud概览 2.1.什么是SpringCloud 2.1.SpringCloud主要组件 ...

  5. Hydra's plan

    省选前的计划,实时更新(不知道能不能把挖的坑填完呢qwq) 链接

  6. Linux学习笔记 一 第三章 Linux常用命令

    第三章Linux常用命令 一.文件处理命令 1.命令格式 2.目录处理命令:ls 3.目录处理命令:mkdir 4.文件处理命令: touch

  7. JDBC+MySQL入门实战(实现CURD的例子)

    前言 hello我是bigsai,今天咱们进行JDBC+MySQL实战,非常适合初入门的小伙伴打开新的世界.实现一个增删改查(curd)的例子.先点赞再观看.帅哥靓女养成好习惯! 在这个案例进行之前, ...

  8. Mybatis中选择语句的使用:<choose>标签、分区排序 Row_num() over ()函数的使用呢

    1.Mybatis中数据库语句的选择 使用: <choose>       <when test="relationType=='L'">          ...

  9. 遗传算法框架-基于java jenetics库实现

    本篇并非介绍如何从0开始开发遗传算法框架,反而推荐各位使用已有的GA库jenetics来做遗传算法. GA算法的逻辑还是贴下: 好了,下面介绍的是基于jenetics开发的更贴近业务侧的框架,以及使用 ...

  10. windows下Nacos集群搭建与nginx集成

    前言: nacos集群至少需要三个(一般为奇数个)nacos实 例,其前面顶nginx,外界入口从nginx入 一.windows下Nacos集群搭建 将Nacos的解压包复制分成3份,分别是: na ...