SetTimeout in javascript not giving the browser a “respite”

Well, I thought I had it all fine, but I seem to be terribly mistaken.

I use excanvas and javascript to draw a map of my home state, however the drawing procedure pinches the browser. Now I'm forced to pander to IE6 because I'm in a large organization, which is probably a significant part of the slowness.

So, I thought that I would create a procedure called DistribDrawPolys (maybe I'm using the wrong word there, so don't focus on the distributed word), which basically pushes the polygons from the global array in order to draw 50 of them at a time.

This is a method that pushes polygons to the global array and runs 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 , . ?

+3
5

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
    }
}
+3

, setTimeout , .

, , , . Semi-:

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 , , , . (Re 10ms: - , 10 .) ( . , , , , , , . , , , " " .)

excanvas, , , , - "", - .

, psuedo- , . . , :

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);
        }
    }
}

... , ( ).

+7

, - .

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); 
+1

. 50 . 50 .

What you can do is bind your setTimeout so that the next function executes after the previous method.

Here's a simple implementation:

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
})();
0
source

If you call it once every five seconds, and each time it performs 1 second of work, the browser will be suppressed for interaction in 20% of cases.

You can try and chop your big function and run it in pieces to make it smoother.

0
source

Source: https://habr.com/ru/post/1737156/


All Articles