前端向后端提交任务启动请求,并接收回执。如果任务执行很快,那么可以在后端任务结束时反馈结果,期间前端可以等待,不太影响用户体验;如果任务执行时间较长,那么可以先返回前端表示后端已经收到并开始执行任务,如果前端后续的工作跟后端这个任务的执行没有时序上的关系,前端可以不用理会任务执行状态和结果,如果前端后续的工作跟这个任务的执行有关,那么前端应主动去查询任务执行状态。
前段时间做的一个web文件上传,出了一个状况,前端分片上传完毕后,向后端发送合并指令,结果后端合并时间居然超过2分钟,http超时了。当然这个跟服务器硬盘io能力弱有关,如果是ssd,可能就不会暴露这个问题。这个大文件大概是30GB左右,我看了下后台文件分片合并速度大概是每秒合并250MB,刚好超过2分钟,然后触发http超时。于是改写了下合并前后端,加入了定时查询,后台反馈合并进度。以后耗时任务一定不能让前端死等,得快速返回,视情况定时查询。
function querystate(filename,fileid){
$.get('/query/'+$("#reqid").val()+'?filename='+encodeURI(filename), (data)=> {
if ($( '#'+fileid ).length > 0) { $( '#'+fileid ).find('span.state').text('后处理中(' + data.status + '%)'); }//页面内显示上传文件队列状态
if (data.status=='100') {
if ($( '#'+fileid ).length > 0) { $( '#'+fileid ).find('span.state').text('后处理完成'); }
window.clearInterval(clocks.find(item=>(item.fileid==fileid)).clockid);
clocks=clocks.filter(item=>(item.fileid!=fileid));
...
}
});
}
...
$.post('/merge_chunks', { 'reqid':$("#reqid").val(), 'name': file.name, },
(data)=> {
if (data.status) {
$( '#'+file.id ).find('span.state').text('上传完成,开始后处理');
let qiv=2000;//2秒
switch (parseInt(file.size/100000000)) {
case 0: qiv/=10; break; //<100MB,查询间隔0.2秒
case 1: case 2: case 3: case 4: qiv/=5; break; //<500MB,查询间隔0.4秒
case 5: case 6: case 7: case 8: case 9: qiv/=2; break; //<1GB 查询间隔 1秒
default: break; //>=1GB 查询间隔 2秒
}
let clockid=setInterval(querystate,qiv,file.name,file.id); //设置定时器
clocks.push(JSON.parse(JSON.stringify({ "clockid":clockid, "fileid":file.id })));
}
else { $( '#'+file.id ).find('span.state').text('后处理出错'); }
},
'json');