好吧,我以为我的整个setTimeout事情很完美,但我似乎非常错误。
我正在使用excanvas和javascript来绘制我的家庭状态的地图,但绘图程序会扼杀浏览器。现在我被迫迎合IE6,因为我是一个大型组织,这可能是缓慢的很大一部分。
所以我认为我要做的是构建一个名为distributedDrawPolys的程序(我可能在那里使用了错误的单词,因此不要专注于分布式单词),这基本上会按顺序从全局数组中弹出多边形一次抽取50个。
这是将多边形推送到全局数组并运行setTimeout的方法:
for (var x = 0; x < polygon.length; x++) {
coordsObject.push(polygon[x]);
fifty++;
if (fifty > 49) {
timeOutID = setTimeout(distributedDrawPolys, 5000);
fifty = 0;
}
}
我在该方法结束时发出警报,它几乎在一秒钟内运行。
分布式方法如下:
function distributedDrawPolys()
{
if (coordsObject.length > 0) {
for (x = 0; x < 50; x++) { //Only do 50 polygons
var polygon = coordsObject.pop();
var coordinate = polygon.selectNodes("Coordinates/point");
var zip = polygon.selectNodes("ZipCode");
var rating = polygon.selectNodes("Score");
if (zip[0].text.indexOf("HH") == -1) {
var lastOriginCoord = [];
for (var y = 0; y < coordinate.length; y++) {
var point = coordinate[y];
latitude = shiftLat(point.getAttribute("lat"));
longitude = shiftLong(point.getAttribute("long"));
if (y == 0) {
lastOriginCoord[0] = point.getAttribute("long");
lastOriginCoord[1] = point.getAttribute("lat");
}
if (y == 1) {
beginPoly(longitude, latitude);
}
if (y > 0) {
if (translateLongToX(longitude) > 0 && translateLongToX(longitude) < 800 && translateLatToY(latitude) > 0 && translateLatToY(latitude) < 600) {
drawPolyPoint(longitude, latitude);
}
}
}
y = 0;
if (zip[0].text != targetZipCode) {
if (rating[0] != null) {
if (rating[0].text == "Excellent") {
endPoly("rgb(0,153,0)");
}
else if (rating[0].text == "Good") {
endPoly("rgb(153,204,102)");
}
else if (rating[0].text == "Average") {
endPoly("rgb(255,255,153)");
}
}
else { endPoly("rgb(255,255,255)"); }
}
else {
endPoly("rgb(255,0,0)");
}
}
}
}
}
编辑:修改格式
所以我认为setTimeout方法允许网站在组中绘制多边形,这样用户就可以在页面仍在绘制时与页面进行交互。我在这里做错了什么?
答案 0 :(得分:7)
如果你的循环在不到一秒的时间内运行,那么所有setTimeout
个来电都会在大约五秒钟之后发起火灾。
如果你想为浏览器提供中间渲染的喘息空间,请将所有对象推送到堆栈中,然后使用限制调用该函数,并在完成许多对象时让函数自行安排。半伪代码:
var theArray = [];
var limit = 50;
function showStuff() {
for (...) {
// push objects on theArray
}
renderArrayInBatches();
}
function renderArrayInBatches() {
var counter;
for (counter = limit; counter > 0; --counter) {
// pop an object and render it
}
if (theArray.length > 0) {
setTimeout(renderArrayInBatches, 10);
}
}
一次性构建数组,然后触发第一批(最多limit
)渲染。在第一批结束时,如果要进行更多渲染,则会将其安排在大约10毫秒后进行。实际上,如果浏览器仍然忙于其他事情,那么它将在10毫秒之后不会发生 ,并且可能晚于此时间。 (重新10ms:大多数浏览器都不会在此之后的10分钟内安排一些事情。)(编辑 Andy E非常正确地指出,您可以将与需要的逻辑相关的逻辑折叠起来。直接渲染到渲染函数中,而不是首先构建数组,然后处理它。除了数组部分之外,不会改变上面的内容,如何进行链接以及“呼吸空间”保持不变。)
不知道你正在使用的excanvas东西,你可能会发现你需要调整超时时间,但我倾向于怀疑它 - 它基本上是一个“收益”操作,让浏览器做一些事情并回到你。
请注意,上面的伪代码示例使用的是全局变量。我不建议实际使用全局变量。您甚至可能想要这样做:
function showStuff() {
var theArray = [];
var limit = 50;
for (...) {
// push objects on theArray
}
renderArrayInBatches();
function renderArrayInBatches() {
var counter;
for (counter = limit; counter > 0; --counter) {
// pop an object and render it
}
if (theArray.length > 0) {
setTimeout(renderArrayInBatches, 10);
}
}
}
...但我不想通过引入闭包来使主要答案复杂化(尽管技术上两个代码块都涉及闭包)。
答案 1 :(得分:3)
将代码更改为
for (var x = 0; x < polygon.length; x++) {
coordsObject.push(polygon[x]);
}
distributedDrawPolys();
function distributedDrawPolys()
{
if (coordsObject.length > 0) {
for (x = 0; x < 50; x++) {
...
}
setTimeout("distributedDrawPolys()", 5000); //render next 50 polys in 5 sec
}
}
答案 2 :(得分:1)
不,你想要一些不同的东西。
var batchsize = 50;
function drawPolys(start) {
for (var x = start; x < polygon.length; x++) {
drawOnePolygon(polygon[x]);
if (start + batchsize <= x) {
// quit this invocation, and schedule the next
setTimeout(function(){drawPolys(x+1);}, 400);
return; // important
}
}
}
然后drawOnePolygon必须是这样的:
function drawOnePolygon(p) {
var coordinate = polygon.selectNodes("Coordinates/point");
//...and so on, continuing from your code above.
}
开始:
drawPolys(0);
答案 3 :(得分:0)
这不能按预期工作。当您的第一个函数开始执行时,您的全局数组已包含50个元素。您最终会对相同的数据进行50次操作。
你可以做的是链接你的setTimeout,以便下一个函数在前一个方法之后执行。
这是一个简单的实现:
var coordObj = [...]; //50 or whatever elements
(function() {
if (coordObj.length === 0) return; //Guardian
var obj = coordObj.pop(); //or .shift(), based on the order desired.
doStuffWithCoordObj(obj);
setTimeout(arguments.callee,0); //call this anonymous function after a timeout
})();
答案 4 :(得分:0)
如果你每五秒钟调用一次,并且每次都进行1秒钟的工作,浏览器会在20%的时间内被阻塞进行交互。
你可以尝试切断你的大功能并以块的形式运行它以使体验更顺畅。