Not blocking the UI in tight JavaScript loops

來源:互聯網
上載者:User

This is

as days pass by, by Stuart Langridge

. Here I write about many things. In the past I wrote about other things but the past is past. I write code for people to play with, I write about my life on Twitter, and I write here.

On Jul 03, 2009 I wrote Not blocking the UI in tight JavaScript loops, on the subject of JavaScript and the DOM. Everyone's written a JavaScript loop that just loops over all the {LIs, links, divs} on a page*, and it's pretty standard. Something like
var lis = document.getElementsByTagName("li"); for (var i=0; i<lis.length; i++) { // yes this could be more efficient, don't care   // do something here to lis[i] };

or, if you're using jQuery:

$("li").each(function() {   // do something here to this });

This is problematic if there are, say, 2000 LI elements on the page, and what you're doing in the loop is semi-intensive (imagine you're creating a couple of extra elements to append to each of those LIs, or something like that). The reason this is a problem is that JavaScript is single-threaded. A tight loop like this hangs the browser until it's finished, you get the "this script has been running for a long time" dialog, and the user interface doesn't update while you're in this kind of loop. You might think: aha, this will take a long time, so I'll have some sort of a progress monitor thing:

var lis = document.getElementsByTagName("li"); for (var i=0; i<lis.length; i++) { // yes this could be more efficient, don't care   // do something here to lis[i]   progressMonitor.innerHTML = "processing list item " + i; // fail };

but that doesn't work. What happens is that the browser freezes until the loop finishes. Annoying, but there it is. One approach to getting around this is with timeouts rather than a for loop.

var lis = document.getElementsByTagName("li"); var counter = 0; function doWork() {   // do something here to lis[i]   counter += 1;   progressMonitor.innerHTML = "processing list item " + counter;   if (counter < lis.length) {     setTimeout(doWork, 1);   } }; setTimeout(doWork, 1); 

so you move the bit of work you need to do into a function, and that function re-schedules itself repeatedly, using setTimeout. This time, your user interface will indeed update, and your progress monitor will show where you're up to. There are a couple of caveats with this: it'll take a bit longer, and you're no longer guaranteed to have things processed in the order you expect, but they're minor issues. For doing this in jQuery, a tiny plugin:

jQuery.eachCallback = function(arr, process, callback) {     var cnt = 0;     function work() {         var item = arr[cnt];         process.apply(item);         callback.apply(item, [cnt]);         cnt += 1;         if (cnt < arr.length) {             setTimeout(work, 1);         }     }     setTimeout(work, 1); }; jQuery.fn.eachCallback = function(process, callback) {     var cnt = 0;     var jq = this;     function work() {         var item = jq.get(cnt);         process.apply(item);         callback.apply(item, [cnt]);         cnt += 1;         if (cnt < jq.length) {             setTimeout(work, 1);         }     }     setTimeout(work, 1); };

and now you can do

$.eachCallback(someArray, function() {   // "this" is the array item, just like $.each }, function(loopcount) {   // here you get to do some UI updating   // loopcount is how far into the loop you are });  $("li").eachCallback(function() {   // do something to this }, function(loopcount) {   // update the UI });

Not always a useful technique, but when you need it, you need it.

http://www.kryogenix.org/days/2009/07/03/not-blocking-the-ui-in-tight-javascript-loops
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.