简体   繁体   English

页面的JavaScript非阻塞更新

[英]JavaScript non-blocking updates to page

I have the following code that runs a loop and updates the page as it goes. 我有以下代码可以运行循环并随页面更新。 At the moment the page does not update until the entire loop has run its course. 目前,直到整个循环运行完毕,页面才会更新。

As you can see, I tried adding a draw function drawValues that is called every 5000 times to draw the current values to the screen. 如您所见,我尝试添加绘制函数drawValues ,该函数每5000次调用一次,以将当前值绘制到屏幕上。 My understanding is that when drawValues is updated, the page should update and then the main loop will resume with its calculations until another 5000 loops. 我的理解是,当drawValues更新时,页面应该更新,然后主循环将继续其计算,直到另外5000循环。

At the moment the page will not update until the loop runs in its entirety, somehow ignoring every other call to drawValues 目前,直到循环完全运行,页面才会更新,以某种方式忽略了对drawValues所有其他调用

Full Snippet: 完整摘要:

 /*jslint browser: true*/ /*global $, jQuery, alert*/ $(document).ready(function() { 'use strict'; var namesAtStart = ["Sam", "John"], specialNum = 8, amountOfNames = namesAtStart.length, counter = [], renderCounter = 0, x, a, loopLength, number, id, preId = "content_", finalId; for (a = 0; a < amountOfNames; a += 1) { counter.push(0); } for (x = 1; x <= specialNum; x += 1) { // Start the counter array at zero for (a = 0; a < amountOfNames; a += 1) { counter[a] = 0; } loopLength = Math.pow(10, x); finalId = preId + loopLength.toString(); $(".output-small").append('<span id="' + finalId + '"></span>'); for (a = 0; a < loopLength; a += 1) { number = Math.floor((Math.random() * amountOfNames) + 1); counter[number - 1] += 1; renderCounter += 1; if (renderCounter == 5000) { drawValues(namesAtStart, counter, finalId, x, a); } if (a == loopLength - 1) { // This is where I am trying to make the code non blocking and async drawValues(namesAtStart, counter, finalId, x, a); } } } }); // This is the part that I want to run when called and update page. function drawValues(names, counter, finalId, id, currentCount) { 'use strict'; var a; $("#" + finalId).empty(); $("#" + finalId).append("<h3>" + Math.pow(10, id).toLocaleString() + "</h1>"); for (a = 0; a < names.length; a += 1) { $("#" + finalId).append( names[a] + ": " + counter[a].toLocaleString() + " (" + (counter[a] / currentCount * 100).toFixed(2) + "%)</br>" ); } $("#" + finalId).append("Numerical Difference: " + Math.abs(counter[0] - counter[1]) + "</br>"); $("#" + finalId).append( "Percentage Difference: " + Math.abs( (counter[0] / currentCount * 100) - (counter[1] / currentCount * 100) ).toFixed(6) + "%</br>" ); $("#" + finalId).append("</br>"); } 
 body {} p, h3 { padding: 0px; margin: 0px; } .container {} .output {} .output-small { margin: 20px; padding: 5px; border: 1px solid rgba(0, 0, 0, 1); width: 300px; border-radius: 10px; } #stats-listing {} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <html> <head> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <title>Roll The Dice</title> <body> <div class="container"> <div class="output" id="stats-listing"> <div class="output-small"></div> </div> </div> <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> <script src="logic.js"></script> </body> </html> 

The main UI thread in browsers, which is used to run JavaScript, is single-threaded. 浏览器中用于运行JavaScript的主UI线程是单线程。 So if you have a function that's taking a lot of time, the browser doesn't update the display. 因此,如果您使用的功能要花费大量时间,则浏览器不会更新显示内容。

To give the browser a chance to update the display, you need to yield back to it by letting your current function end and scheduling a timed callback to another run of it for the next block of updates, via setTimeout . 为了使浏览器有机会更新显示,您需要让当前函数结束并通过setTimeout为下一个更新块安排定时回调到另一个运行,以便让浏览器恢复显示。 You'll have to experiment with the browsers you want to support to determine the delay in the timed callback; 您必须尝试使用​​要支持的浏览器来确定定时回调中的延迟。 some browsers are happy with 0 (call back as soon as possible), others want longer (50 — 50 milliseconds — is plenty for every browser I know). 有些浏览器对0(尽快回叫)感到满意,而另一些浏览器则希望更长(50 – 50毫秒–对于我所知道的每个浏览器都足够)。

Here's a simple example that adds 10 boxes to the page, yields, then adds another 10, yields, etc. until it's done 1,000 boxes: 这是一个简单的示例,该示例向页面添加10个框,产生,然后再添加10个框,产生等等,直到完成1,000个框:

 (function() { var total = 0; addBoxes(); function addBoxes() { var n; for (n = 0; n < 10 && total < 1000; ++n, ++total) { box = document.createElement('div'); box.className = "box"; document.body.appendChild(box); } if (total < 1000) { setTimeout(addBoxes, 10); // 10ms } } })(); 
 .box { display: inline-block; border: 1px solid green; margin: 2px; width: 20px; height: 20px; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM