代码之家  ›  专栏  ›  技术社区  ›  Midhat

显示JavaScript执行进度

  •  12
  • Midhat  · 技术社区  · 14 年前

    我有一些需要1到3秒的javascript函数。(一些循环或MOOML模板代码。)

    在此期间,浏览器只是被冻结。我尝试在开始操作之前显示一个“加载”动画(gif图像),并在单词后隐藏它。但它不起作用。浏览器会在渲染图像之前冻结,并在函数结束时立即隐藏。

    在进入JavaScript执行之前,我能做些什么让浏览器更新屏幕吗?比如application.doEvents或后台工作线程。

    关于如何显示JavaScript执行进度的任何评论/建议。我的主要目标浏览器是IE6,但也应该适用于所有最新的浏览器。

    4 回复  |  直到 14 年前
        1
  •  19
  •   Sean Kinsey    14 年前

    这是因为IE6中的所有内容都是在同一线程中执行的,甚至是对GIF进行动画处理。

    确保在开始之前显示GIF的唯一方法是分离执行。

    function longRunningProcess(){
        ....
    
        hideGif();
    }
    
    displayGif();
    window.setTimeout(longRunningProcess, 0);
    

    但这仍然会使浏览器在 longRunningProcess 执行。
    为了允许交互,您必须将代码分解成更小的片段,也许像这样

    var process = {
        steps: [
            function(){
                // step 1
                // display gif
            },
            function(){
                // step 2
            },
            function(){
                // step 3
            },
            function(){
                // step 4
                // hide gif
            }
        ],
        index: 0,
        nextStep: function(){
            this.steps[this.index++]();
            if (this.index != this.steps.length) {
                var me = this;
                window.setTimeout(function(){
                    me.nextStep();
                }, 0);
            }
        }
    };
    
    process.nextStep();
    
        2
  •  1
  •   ob1    14 年前

    也许你可以在显示动画gif和运行重代码之间延迟一段时间。

    显示GIF,然后调用:

    window.setTimeout(myFunction, 100)
    

    做“我的功能”中的重活。

        3
  •  1
  •   Juriy    14 年前

    您必须使用更复杂的技术来显示长时间运行函数的进度。

    假设您有一个这样的函数,运行时间足够长:

    function longLoop() {
        for (var i = 0; i < 100; i++) {
            // Here the actual "long" code
        }
    }
    

    为了保持界面的响应性和显示进度(也为了避免在某些浏览器中出现“脚本耗时太长…”的消息),必须将执行过程分成几个部分。

    function longLoop() {
        // We get the loopStart variable from the _function_ instance. 
        // arguments.callee - a reference to function longLoop in this scope
        var loopStart = arguments.callee.start || 0;
    
        // Then we're not doing the whole loop, but only 10% of it
        // note that we're not starting from 0, but from the point where we finished last
        for (var i = loopStart; i < loopStart + 10; i++) {
            // Here the actual "long" code
        }
    
        // Next time we'll start from the next index
        var next = arguments.callee.start = loopStart + 10;
        if (next < 100) {
    
            updateProgress(next); // Draw progress bar, whatever.
            setTimeout(arguments.callee, 10);
        }
    }
    

    我没有测试过这个实际的代码,但是我以前使用过这个技术。

        4
  •  0
  •   Igor Zinov'yev    14 年前

    尝试设置 wait 在运行函数之前使用光标,然后将其移除。在jquery中,您可以这样做:

    var body = $('body');
    body.css("cursor", "wait");
    lengthyProcess();
    body.css("cursor", "");