开发者

Javascript: how to update page before onClick is complete?

I have a function that's designed to parse a 20MB XML file. It works well, but I'd like to give some progress indication during the minute or so it takes.

This, however, doesn't work:

<head>

<script type="text/javascript">

function pauseJS(timeInMilliS) {
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < timeInMilliS);
}

function process() {
    for (var i = 0; i<=10; i++) {
        document.images["bar"].width += 5;
        document.images["bar"].h开发者_如何学Pythoneight = 5;      
        pauseJS(500);
    }
}
</script>

</head>

<body>
    <input type="button" value="Go" onClick="process()"> 
    <img src="black.gif" name="bar" width=1 height=5 />
</body>

(pauseJS stands in for the processing) The progress bar would only update once processing is done, not during.

I saw a similar question, but setTimeout doesn't seem to help in this scenario.


setTimeout is exactly how you deal with this, but you have to structure your parsing function correctly. The last thing you want to do is the busy-wait shown in pauseJS. That doesn't pause JavaScript, that makes JavaScript run maniacally until the time is reached or the browser cancels the script for being over-consumptive. :-)

To allow the browser a moment to update the page display, you must make the JavaScript thread yield back to the browser. So for instance, this will not work:

var TOTAL = 10000000;
var BATCH = 10000;

function doSomething() {
    for (n = 0; n < TOTAL; ++n) {
        if ((n % BATCH) == 0) {
            // ...change progress indicator...
        }

        // ...do processing...
    }
}

...because it never yields. This, on the other hand, works:

var TOTAL = 10000000;
var BATCH = 10000;

function doSomething() {
    var n = 0;

    work();

    function work() {
        var maxn = Math.min(n + BATCH, TOTAL);

        for ( ; n < maxn; ++n) {
            // ...do processing...
        }

        // ...update progress indicator...

        if (n < TOTAL) {
            setTimeout(work, 0);
        }
    }
}

As you can see, here we're breaking the work up into discrete batches, and periodically stopping, scheduling the next batch of work, and returning control to the browser. This gives it a moment to update the page, after which it will call us back (not after 0ms literally, but when it next can, which will typically be however it takes to update itself plus 5-10ms).


Javascript has only one thread, meaning there's no way you can do more than one thing at once.

You'll have to break the XML processing function up so it does a chunk of work, updates the progress bar, and so on.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜