循环比休息更重要?

时间:2013-08-20 15:28:23

标签: javascript loops

我想在用户点击我的按钮时执行简单的代码:

  1. 首先:将光标改为'等待'
  2. 下一步:执行循环
  3. 循环结束时:将光标更改回“默认”
  4. 我写了这段代码:

    HTML:

    <button type="button" id="gogogo">Go!</button>
    
    <div id="progress">0</div>
    

    JS:

    var progress = document.getElementById('progress');
    
    document.getElementById('gogogo').onclick = (function(){
      document.body.style.cursor = 'wait';
    
      for(var ii = 0; ii < 30000; ii += 1){
        progress.textContent = ii;
      }
    
      document.body.style.cursor = 'default';
    
    });
    

    此处的实时代码:http://jsfiddle.net/4Bz27/2/

    出了点问题。首先循环执行,然后发生光标更改。 是否可能或以任何方式与异步相关?

4 个答案:

答案 0 :(得分:2)

您正在执行阻止操作。这肯定会在某些时候引起缓慢的脚本警告。你可以通过使循环异步来解决这个问题:

var progress = document.getElementById('progress');

document.getElementById('gogogo').onclick = (function(){
    document.body.style.cursor = 'wait';

    var index = 0,
        updater;

    updater = function() {
        progress.textContent = index++;

        if (index < 30000) {
            setTimeout(updater, 50);
        } else {
            document.body.style.cursor = 'default';           
        }
    };

    updater();
});

答案 1 :(得分:2)

仅在调用堆栈完成后才应用样式。您可以通过从setInterval运行函数的后半部分将它分成两个不同的调用堆栈,如下所示:

var progress = document.getElementById('progress');

document.getElementById('gogogo').onclick = (function(){
    document.body.style.cursor = 'wait';

    setTimeout(function(){

        for(var ii = 0; ii < 30000; ii += 1){
            progress.textContent = ii;
        }

        document.body.style.cursor = 'default';
    }, 0);

});

答案 2 :(得分:2)

RequestAnimationFrame Way

jsFiddle here

(function (W) {
    W.onload = function () {
        var D = W.document,
            a = 0,
            c = D.getElementById('progress');

        function b() {
            c.innerText = a + 1;
            a++;
            if (a < 500) {
                requestAnimationFrame(b);
            } else {
                D.body.style.cursor = 'default';
            }
        }

        function start() {
            D.body.style.cursor = 'wait';
            b()
        }
        D.getElementById('gogogo').onclick = start;
    }
})(window)

通过这种方式,您可以使用更少的资源,因此复杂的链接修改不会减慢其他开放网站的速度。

答案 3 :(得分:1)

您的循环发生得太快,无法显示任何结果。

一切都已完成,但约为&lt; 1毫秒。 您可以使用超时来延迟显示的内容,以便您可以看到正在发生的事情。

编辑:这是JsFiddle链接: http://jsfiddle.net/4Bz27/9/

var progress = document.getElementById('progress');

var restoreCursor= function () {
   document.body.style.cursor = 'default';
 }

document.getElementById('gogogo').onclick = (function(){
    document.body.style.cursor = 'wait';

    var ii = 0;
    // this is a immediately executed function
    //that calls itself with a small timeout  
    (function goLoop(){

        progress.textContent = ii;

        if(ii<30000){
           ii++;
           setTimeout(goLoop,10);
        }else {
          restoreCursor();
        }

    })();



});

用那个替换你的jsFiddle,你很高兴。

为了更好的表现,我会迭代每一帧。 像这样:

var ii =0;
(function goLoop(){
  progress.textContent = ii;
  if(ii>3000) {
    ii++;
    requestAnimationFrame(goLoop);
})();