6

我试图在非常密集的 JavaScript 期间创建一个加载栏,其中构建和填充了一些非常重的 3d 数组。在用户单击按钮之前,此加载栏需要保持空白。

无论我是否使用,都会发生冻结-webkit-transition(这个应用程序可以是 chrome 独有的,在我的情况下不需要跨浏览器)。

寻求简单我已经建立了这样的酒吧......

<div id="loader">
    <div id="thumb">
    </div>
</div>

...然后试图在我的主for循环的各个阶段增加该栏:

for(i = 0; i < 5 ; i++){
    document.getElementById('thumb').style.width = i*25 + '%';
    //More Code
}

问题是一切都冻结了,直到 JavaScript 完成。我在 Stack Overflow 上发现了一个类似的问题,在 javascript 计算时使用 CSS 动画,在评论中发现并考虑和/或尝试了以下内容:

  • 网络工作者

    不要认为它会起作用,因为我的脚本正在用对象和构造函数填充数组,这些对象和构造函数包含根据本网站无法正常工作的函数

  • jQuery

    不是一个选项,我不能在我的应用程序中使用外部库 - 无论如何,仅为加载栏导入整个库似乎有点矫枉过正......

  • 关键帧

    这是有希望的,我试过了,但最后它也冻结了,所以没有快乐

  • timeOut()s

    想过这个,但既然加载栏的目的是减少挫败感,增加等待时间似乎适得其反

我很乐意在这个阶段增加条形,即使它不平滑我很确定这不仅仅是我一个人遇到的问题——也许有人有一个有趣的解决方案?

PS:我将其作为一个新问题发布,而不是添加到引用的问题中,因为我专门寻求 JavaScript(不是 jQuery)的帮助,并且如果我可以使用宽度上的转换(!=动画)来获得它,我更愿意.

4

2 回答 2

5

有些人已经提到你应该使用超时。这是适当的方法,因为它会让浏览器有时间“呼吸”并在任务中呈现进度条。

您必须拆分代码才能异步工作。假设您目前有这样的事情:

function doAllTheWork() {
  for(var i = 0; i < reallyBigNumberOfIterations; i++) {
    processorIntensiveTask(i);
  }
}

然后你需要把它变成这样的东西:

var i = 0;
function doSomeWork() {
  var startTime = Date.now();
  while(i < reallyBigNumberOfIterations && (Date.now() - startTime) < 30) {
    processorIntensiveTask(i);
    i++;
  }

  if(i < reallyBigNumberOfIterations) {
    // Here you update the progress bar
    incrementBar(i / reallyBigNumberOfIterations);

    // Schedule a timeout to continue working on the heavy task
    setTimeout(doSomeWork, 50);
  }
  else {
    taskFinished();
  }
}

function incrementBar(fraction) {
  console.log(Math.round(fraction * 100) + ' percent done');
}

function taskFinished() { console.log('Done!'); }

doSomeWork();

注意表达式(Date.now() - startTime) < 30。这意味着循环将在 30 毫秒的跨度内完成尽可能多的工作。你可以让这个数字更大,但是从用户的角度来看,任何超过 100 毫秒(基本上是每秒 10 帧)的时间都会开始变得迟缓。

与同步版本相比,使用这种方法可能会花费更长的时间来完成整个任务。然而,从用户的经验来看,有某事正在发生的迹象比在似乎什么都没有发生的情况下无限期地等待要好——即使后者的等待时间更短。

于 2012-11-19T21:12:26.397 回答
1

您是否尝试过更简单并创建一个函数,比如说:

伪:

Function increment_bar(amount = 10)
{
 document.getElementById('thumb').style.width = i*amount + '%';
}

然后,无论您在哪里进行处理工作,只需每隔 x 秒或每当您在处理中达到某个特定点时调用该函数(比如说 10-20% 的完成度?)

伪:

{
    Doing_work_here;
    increment_bar(25);
    LOOP
}
于 2012-11-19T20:47:40.107 回答