javascript中的setTimeout没有给浏览器'呼吸空间'

C B*_*uer 3 javascript xml settimeout excanvas census

好吧,我以为我的整个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;
      }
 }
Run Code Online (Sandbox Code Playgroud)

我在该方法结束时发出警报,它几乎在一秒钟内运行.

分布式方法如下:

 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)");
                     }
                }
           }
      }
 }
Run Code Online (Sandbox Code Playgroud)

编辑:修复格式

所以我认为setTimeout方法允许网站在组中绘制多边形,这样用户就可以在页面仍在绘制时与页面进行交互.我在这做错了什么?

T.J*_*der 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样就可以一次性构建数组,然后触发第一批(最多limit)渲染.在第一批结束时,如果要进行更多渲染,则会将其安排在大约10毫秒后进行.事实上,就不会发生迟早超过10ms后,很可能晚于,如果浏览器仍忙于其他事情.(重新10ms:大多数浏览器从现在开始不会在10ms之后安排一些事情.)(编辑 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

...但我不想通过引入闭包来使主要答案复杂化(尽管技术上两个代码块都涉及闭包).

  • 我输入了类似的答案,所以+1.另一个选择是取消for循环并让每个`distributedDrawPolys()`调用为下一个10ms左右的时间设置定时器. (2认同)