【问题标题】:How much to subdivide long running function for responsive UI?为响应式 UI 细分长时间运行的功能需要多少?
【发布时间】:2010-11-10 22:11:51
【问题描述】:

我有一个运行时间相当长(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

现在,我进行了一些测试,产生大约 100 毫秒执行时间的 chunkSize 和 1 毫秒 timeout 似乎产生了一个响应非常灵敏的 UI,但我看到的一些示例推荐更大的块 ( ~300 毫秒)和更长的超时时间(20 到 100 毫秒)。将我的函数切割成太多的小块,我是否遗漏了一些危险,或者反复试验是确定这些数字的安全方法?

【问题讨论】:

  • 您确实意识到机器的JavaScript(客户端)CPU,内存,网络连接等因素非常重要。
  • @Jason McCreary,当然。这就是为什么我要问这个问题,而不是假设我确定这些数字的试错法是安全的。

标签: javascript settimeout


【解决方案1】:

任何小于大约 15 毫秒的超时值都是等效的 - 浏览器将更新 DOM 等,然后执行超时。有关更多信息,请参阅 thisthis。我倾向于使用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

【讨论】:

  • 我喜欢在实际客户端上计时的想法,尽管我认为我会使用第一次运行来获得每次迭代的粗略平均时间,然后将所有后续运行设置为合理的以此为基础计算。
【解决方案2】:

1ms 超时实际上并不是 1ms。当线程屈服时,要达到 1 毫秒,它可能会产生更多——因为典型的线程时间片是 30 毫秒。在 1 毫秒超时期间,可能已经执行了任意数量的其他线程,这可能意味着在您再次获得控制权之前已经过去了 200 毫秒。

为什么不让“doSomethingWithData”在完全不同的线程中执行?

【讨论】:

  • 这是javascript:只有一个线程。至少,现在的浏览器只有一个线程。
  • 在网络工作者普及之前(超过 90% 的浏览器),我不会指望有多个线程来执行我的 javascript。
猜你喜欢
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 2011-01-25
  • 2012-09-08
  • 2021-12-28
  • 2017-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多