3

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

  1. 第一:将光标更改为“等待”
  2. 下一步:执行循环
  3. 循环完成时:将光标改回“默认”

我写了这段代码:

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

4 回答 4

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();
});
于 2013-08-20T15:39:45.700 回答
2

RequestAnimationFrame 方式

jsFiddle在这里

(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)

这样您可以使用更少的资源,因此您的复杂链接修改不会减慢其他打开的网站。

于 2013-08-20T16:07:48.530 回答
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);

});
于 2013-08-20T15:47:37.703 回答
1

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

一切都完成了,但在大约 < 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);
})();
于 2013-08-20T15:39:07.400 回答