我有一个相当长的运行时间(3到10秒),它在后台加载数据,用于页面中相当不常用的部分。我的问题是每次执行的最佳运行时间和确保页面其余部分保持相当交互的延迟时间是多少,但是通过分解数据加载不会过度延迟?
例如:
var i = 0;
var chunkSize = 10;
var timeout = 1;
var data; //some array
var bigFunction = function() {
var nextStop = chunkSize + i; //find next stop
if (nextStop > data.length) { nextStop = data.length }
for (; i < nextStop; i++) {
doSomethingWithData(data[i]);
}
if (i == data.length) { setTimeout(finalizingFunction, timeout); }
else { setTimeout(bigFunction , timeoutLengthInMs); }
};
bigFunction(); //start it all off
现在,我已经完成了一些测试,并且chunkSize
产生大约100毫秒的执行时间和1毫秒timeout
似乎产生了一个非常灵敏的用户界面,但是我见过的一些例子推荐更大的块(约300毫秒)和更长的超时(20到100毫秒)。我是否遗漏了将我的功能削减成太多小块的危险,或者试错是一种确定这些数字的安全方法?
答案 0 :(得分:3)
任何超过大约15ms的超时值都是等效的 - 浏览器将更新DOM等,然后执行超时。有关详细信息,请参阅this和this。我倾向于使用setTimeout(fn, 0)
。
我会检查过去的时间而不是猜测数字,因为正如Jason指出的那样,客户之间会有速度差异:
var data; // some array
var i = 0;
var MAX_ITERS = 20; // in case the system time gets set backwards, etc
var CHECK_TIME_EVERY_N_ITERS = 3; // so that we don't check elapsed time excessively
var TIMEOUT_EVERY_X_MS = 300;
var bigFunction = function () {
var maxI = i + MAX_ITERS;
if (maxI > data.length) { maxI = data.length }
var nextTimeI;
var startTime = (new Date()).getTime(); // ms since 1970
var msElapsed;
while (i < maxI) {
nextTimeI = i + CHECK_TIME_EVERY_N_ITERS;
if (nextTimeI > data.length) { nextTimeI = data.length }
for (; i < nextTimeI; i++) {
doSomethingWithData(data[i]);
}
msElapsed = (new Date()).getTime() - startTime;
if (msElapsed > TIMEOUT_EVERY_X_MS) {
break;
}
}
if (i == data.length) {
setTimeout(finalizingFunction, 0);
} else {
setTimeout(bigFunction , 0);
}
};
bigFunction(); //start it all off
答案 1 :(得分:0)
1ms超时实际上不是1 ms。当线程产生时,为了达到1ms,它可能产生更多 - 因为典型的线程时间片是30ms。在1ms超时期间可能已执行任意数量的其他线程,这可能意味着在您再次接收控制之前已经过了200ms。
为什么不在完全不同的线程中执行'doSomethingWithData'呢?