我有一个数据集,在该数据集上迭代并在每个元素上运行相当繁重的操作。为了防止浏览器冻结,我将超时设置为0ms。虽然浏览器不会冻结,但是根据用户的输入,计算可能需要花费好几秒钟的时间。这是代码:
function calculation(){
$.each(data,function(key,value){
setTimeout(function(){
doTheHeavyLifting(value);
},0);
});
}
现在的问题是,如果用户要求使用新值再次运行计算,我想停止先前的计算。
我尝试在函数外部定义
continueCalculating
布尔值,并在调用false
之前在runCalculation()
中将其设置为calculation()
,然后在calculation()
内部将其重置为true
。这是修改后的代码:var continueCalculating=false;
function runCalculator(){
continueCalculating=false;
calculation();
}
function calculation(){
continueCalculating=true;
$.each(data,function(key,value){
setTimeout(function(){
if(continueCalculating){
doTheHeavyLifting(value);
}else{
console.log("Abort the mission!");
return false;
}
},0);
});
}
好吧,这并不能解决问题,回想起来,这还是一个很愚蠢的主意。因此,接下来我也尝试清除所有超时。这是修改后的代码:
var continueCalculating=false;
var operationQueue=[];
function runCalculator(){
continueCalculating=false;
$.each(operationQueue, function(k,v){
clearTimeout(v);
});
calculation();
}
function calculation(){
continueCalculating=true;
$.each(data,function(key,value){
operationQueue.push(setTimeout(function(){
if(continueCalculating){
doTheHeavyLifting(value);
}else{
console.log("Abort the mission!");
return false;
}
},0));
});
}
好吧,那也没有产生任何结果。
我知道
$.each
比for
慢,但是要迭代的项目大约只有几十个,因此这里肯定不是瓶颈。我不是在寻找优化此代码的方法,我只需要停止正在进行的计算即可。这可能吗? 最佳答案
您应该异步迭代:
var data = [0,1,2,3,4,5,6,7,8,9,"end"];
function doTheHeavyLifting(value) {
console.log(value);
}
function calculation(data) {
var key = 0, timer;
(function loop() {
if(key < data.length) {
doTheHeavyLifting(data[key]);
key++;
timer = setTimeout(loop, 1e3);
}
})();
return {stop: function() { clearTimeout(timer) } };
}
var calc = calculation(data);
document.querySelector('#stop').onclick = calc.stop;
<button id="stop">Stop</button>