step1.前端携带资源id向后台发起下载请求,后台针对此次下载请求生成一个任务号taskno+一个数据版本号dataver返回给前端;
step2.前端携带上一步得到的任务号和版本号向后台异步发送下载开始指令,后台开始使用异步多线程机制处理大数据,并将格式化之后的数据push到redis的队列中;与此同时,前端起动了一个轮循器,定时向后台询问数据是否处理完毕。(此轮循器具有自动超时断开机制,不必担心无限制轮循)
step3.当得知后台已经处理完处理之后,前端终止轮循,并跳转到后台提供的下载地址,完成数据的下载工作。
function AsyncExporter(options){ this.requestUrl = options.requestUrl; this.exportUrl = options.exportUrl; this.interval = options.interval || 1000; this.onComplete = options.onComplete; this.onProgress = options.onProgress; this.autoDownload = options.autoDownload || false; this.timerId = 0; this.targetUrl = ''; this.startTime = 0; this.endTime = 0; if(!this.requestUrl || !this.requestUrl){ throw 'params is required!'; } this.onStart = function(){ this.startTime = (new Date()).getTime(); } this.onEnd = function(){ this.endTime = (new Date()).getTime(); console.log('Total time:'+(this.endTime - this.startTime)); typeof(this.onComplete)=='function' && this.onComplete(this.targetUrl); } this.requestExport = function(){ var self = this; $.ajax({ url: this.requestUrl, type: 'POST', data: {'action':'create'}, dataType: 'json', success: function(e){ if(e.status==1){ self.onStart(); self.doTask(e.taskno, e.dataver); //return self.onComplete();//debug self.callLoop(function(){ self.askforstate(e.taskno, e.dataver); }); }else{ alert(e.msg); } } }); } this.doTask = function(taskno, dataver){ $.ajax({ url: this.requestUrl, type: 'POST', data: {'action':'dotask', taskno:taskno, dataver:dataver}, dataType: 'json', async: true, success: function(e){} }); } this.askforstate = function(taskno, dataver){ var self = this; $.ajax({ url: this.requestUrl, type: 'POST', data: {action:'askfor', taskno:taskno, dataver:dataver}, dataType: 'json', success: function (e){ typeof(self.onProgress)=='function' && self.onProgress(e.curnum); if(e.status==1){ self.download(e.taskno, e.dataver); self.stopLoop(); self.onEnd(); } }, complete: function(e){ } }); } this.buildTargetUrl = function(taskno, dataver){ this.targetUrl = this.addQuery(this.exportUrl,'taskno='+taskno+'&dataver='+dataver); return this.targetUrl; } this.download = function(taskno, dataver){ var targetUrl = this.buildTargetUrl(taskno, dataver); if(this.autoDownload){ //window.open(, 'DownloadWindow'); var a = document.createElement('a'); a.target='_blank'; a.href = targetUrl; a.click(); } return this; } this.callLoop = function(func){ this.timerId = setInterval(function(){ typeof(func) == 'function' && func(); }, this.interval); return this; } this.stopLoop = function(){ clearInterval(this.timerId); this.timerId = 0; return this; } this.addQuery = function (url, query){ if(url.indexOf('?')>0){ return url+'&'+query; }else{ return url+'?'+query; } } this.start = function(){ this.requestExport(); setTimeout((function(self){ return function(){ if(self.timerId>0){ alert('请求超时'); self.stopLoop(); self.onEnd(); } } })(this), 1000*60*10); } }调用方法:
downloadBtn.onclick=function(){ var exporter = new AsyncExporter({ requestUrl:'requestExport?formcode={$formcode}', exportUrl: 'dumpRecordData?formcode={$formcode}', onComplete: function(url){ setTimeout(function(){ url && window.open(url, 'DownloadWindow'); }, 1000); }, onProgress: function(curnum){ console.log(curnum); total>0 && tipsJq.text((curnum/total*100).toFixed(2) + '%'); } }); exporter.start(); }