js的定时器 实现页面展示的异步刷新 附进度条js代码

版权声明:转载请注明出处 https://blog.csdn.net/h2604396739/article/details/86598442

先简单介绍下场景
按条件进行大量数据的查询,因为数据量大的原因,导致可能40秒结果都还没有出来,所以后台采用多线程实现异步的处理方式,先返回;但是问题是查询完成的时候,怎么可以让查询的结果自动展示到前台页面呢?
采用方案:
给被查询页面增加刷新标志,表里面增加字段status,值只能是0或1,0:不需要刷新,1:需要刷新
status的默认值是0。
页面点击查询按钮:
1进度条展示开始,数据统计并入表开始,在统计完成的时候,将status更新为1,怎么确定数据统计完成呢,所有多线程的future.get调用完毕
2页面增加定时查看status的任务开始,status=0,不需要刷新;status=1,需要刷新页面,将status重置为0,返回需要刷新页面的标志,前端进行页面的刷新,同时删除页面里面的js定时器和进度条。

整体代码
点击查询按钮调用的方法--开始查询,并且开始定时任务

// 全局变量 定时器
var t1;

/**
 * ajax异步调用多线程开始数据统计,并且开始定时器任务
 *
 * @param pageId
 * @param pageType
 */
function queryAndSaveResult(pageId,pageType){
    // 参数准备及整理 
    // 这里页面增加加载进度条
    __showLoading();
    // ajax请求开始数据查询
    $.ajax({
        type: "POST",
        url: "../bireport/queryAndSaveResult.action",
        contentType : "application/json",
        timeout:20000,
        dataType:"html",
        data: JSON.stringify(json),
        success: function(resp){
            // 开启定时器获取status,status=0:不需要刷新;status=1,需要刷新页面,且刷新后将status重置为0,同时删除页面里面的js定时器
            t1=window.setInterval("refreshPage(pageId,pageType,t1)", 1000);
        },
        error:function(resp){
            $.messager.alert('出错了','系统出错,请联系管理员。','error');
        }
    });

}

后台的查询代码:统计数据,统计数据完成后,异步更新status为1


    /**
     * 功能描述: 按照查询条件保存日活数据
     *
     * @param:
     * @return:
     * @auther: mazhen
     * @date: 2018/9/3 下午8:03
     */
    @RequestMapping(value="/queryAndSaveResult.action", method = RequestMethod.POST)
    public @ResponseBody
    Object queryAndSaveResult(@RequestBody ResultCondition timeInterval) throws InterruptedException/* throws Exception*/ {
        //1、查询参数整理与数据准备
        //2采用了线程池,异步进行数据查询和保存
        ArrayList<Future> futures = new ArrayList<>();
        for(final RhQueryConditionNew dto:rhQueryConditionDtos){
            times = timeOfCondition.get(dto.getId());
            // 逐日往后推,判断改日的数据是否已经存在,如果已经存在则不查询
            while(currentTimems<=endTimems) {
                // 说明该条件下的该日期没有查询过,则if里面查询从改日到最后一日的数据
                if (!times.contains(dateFormat1.format(currentTimems))) {
                    isSleep = true;
                    Future<?> submit = fixedThreadPool.submit(new QueryTask(dto, dateFormat1.format(currentTimems), endTimeStr, pageId, pageType, rhService));
                    futures.add(submit);
                    // 上面查询到最后日期的数据所以没有必要再进行循环判断了,直接break
                    break;
                }
                currentTimems += oneDay;
            }
           
        }

        // 新开一个异步线程,设置线程,futures执行完毕设置status为1,表示需要刷新展示
        new Thread(new PageStatusTask(futures,pageId,olapService)).start();

        Result ret = new Result();
        ret.setResult(RequestStatus.SUCCESS.getStatus());
        return ret;
    }

后台异步设置status的线程代码:数据统计完成,将status更新为1

public class PageStatusTask implements Runnable{
    static Logger logger = Logger.getLogger ( PageStatusTask.class ) ;

    ArrayList<Future> futures ;
    String pageId  ;

    OlapService service;

    public PageStatusTask(ArrayList<Future> futures ,String pageId,OlapService service){
        this.futures =futures;
        this.pageId = pageId;
        this.service = service;
    }

    @Override
    public void run() {
        for(Future future : futures){
            try {
                future.get();
            } catch (Exception e) {
                logger.error("");
            }

        }
        // 所有线程的future.get执行完毕,说明查询已经完成,可以刷新页面的展示了
        service.updateOlapStatus(Integer.parseInt(pageId), 1);
    }
}

前端获取status的值并进行对应的操作

/**
 * 定时查看当前页面是否需要刷新展示,status=0,不需要刷新;status=1,需要刷新页面,且刷新后将status重置为0,同时删除页面里面的js定时器
 * @param pageId 页面id
 * @param pageType 页面类型
 * @param t1
 */
function refreshPage(pageId,pageType,t1){
    var 	startTime =  $("#dfm1").val();
    var     endTime=  $("#dfm2").val();
    var json = {
        pageId:pageId
    };
    $.ajax({
        type: "POST",
        url: "../bireport/queryAndResetPageStatus.action",
        contentType : "application/json",
        timeout:2000000,
        dataType:"html",
        data: JSON.stringify(json),
        success: function(resp){
            // status=0,不需要刷新;status=1,需要刷新页面,且刷新后将status重置为0,同时删除页面里面的js定时器
            if("1"==resp){
                openRhShowPage(startTime,endTime,pageId,pageType);
                __hideLoading();
                window.clearInterval(t1);
            }else{
                console.log("still querying---");
            }
        },
        error:function(resp){
            $.messager.alert('出错了','系统出错,请联系管理员。','error');
        }
    });
}


前端定时任代码逻辑如下:先获取status,status=0,不需要刷新;status=1,需要刷新页面,且刷新后将status重置为0,同时删除页面里面的js定时器


使用js定时器的注意点

方法带引号不不带引号的区别:带引号会一直执行,但是如果不带引号则仅仅执行一次

如;

window.setInterval("refreshPage(pageId,pageType,t1)", 1000);//一直执行  
window.setInterval(refreshPage(pageId,pageType,t1), 1000);//执行一次 

定时的方法中的参数,一定需要是全局变量,如果参数时局部变量,就会出现第一次方法能正常执行,但是第二次及以后参数就变为undefined了。如上面refreshPage(pageId,pageType,t1)中的pageId和pageType。

进度条显示和隐藏的代码如下


function __showLoading(){
	var sload = $('#loadingdiv');
	if(sload.size() == 0){
		sload = $('<div id="loadingdiv" class="sk-spinner sk-spinner-three-bounce" style="position:absolute;z-index:9999"><div class="sk-bounce1"></div><div class="sk-bounce2"></div><div class="sk-bounce3"></div></div>').appendTo('body');
		window.loadCompCnt = 1;	
	}else{
		window.loadCompCnt =  window.loadCompCnt + 1;
	}
	var doc = $(document);
	var win = $(window);
	var t = doc.scrollTop() + win.height()/2 - 50;
	var l = doc.scrollLeft() + win.width()/2 - 50;
	sload.css({'top':t, 'left':l});
	sload.show();
}

function __hideLoading(){
	window.loadCompCnt =  window.loadCompCnt - 1;
	if(window.loadCompCnt == 0){
		$("#loadingdiv").remove();
		delete window.loadCompCnt;
	}
}

猜你喜欢

转载自blog.csdn.net/h2604396739/article/details/86598442