setTimeoutをJavaScriptでブラウザの呼吸の部屋」を与えていません
-
20-09-2019 - |
質問
さてさて、私は、この全体の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メソッドは、ユーザーが、それはまだ描いていた間、ページと対話できるようになるので、サイトには、グループ内のポリゴンを描画することが可能だろうと思いました。私はここで間違って何をしているのですか?
解決
タグにコードを変更します
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
}
}
他のヒント
あなたのループが第二の下で実行されている場合は、あなたのsetTimeout
呼び出しのすべてが、約5秒後にオフに解雇しようとするまでスタックします。
あなたは、中間レンダリングのためのブラウザの余裕を与え、スタック上のすべてのオブジェクトをプッシュし、その後、制限付き関数を呼び出し、それが多くのオブジェクトことを行うの際に、機能、スケジュール自体を持っているしたい場合。セミ擬似コード:
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ミリ秒のために何かをスケジュールしません)(編集アンディ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);
}
}
}
...しかし、私は(技術的には、両方のコードブロックはクロージャを伴うが)閉鎖を導入することにより、メインの答えを複雑に好きではありませんでした。
いいえ、あなたは別の何かをしたいです。
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);
、ブラウザが相互作用のための時間の20%を窒息されます。
あなたは経験をよりスムーズにするために試してみて、あなたの大切な機能を切り刻むとチャンクでそれを実行することができます。
これは動作しません。あなたの最初の関数が実行を開始時点で、あなたのグローバルな配列は、すでに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
})();