2

20秒ごとに(setInterval関数を使用して)ajaxリクエストを起動し、フォーマットでレスポンスを取得するJavaScript ajaxページがありJSONます。ページ内。Googleマップにマーカーを表示し(API v3を使用)、レスポンスJSONから受け取った場所に基づいて20秒ごとに更新しています。マーカーのクリックイベントをajax表示しています。infoWindow

サーバー側のスクリプトとして PHP を使用しています。これは、いくつかの DB 呼び出しを実行して ajax 応答を生成します。

ページを開くと、すべて正常に動作します。しかし、ゆっくりとページの応答が遅くなり始めます。つまり、マーカーまたは関連テキストをクリックすると、ページがマーカーを見つけ、マップをロードし、infoWindow. また、時間の経過とともにページの速度が遅くなります。ページを更新すると、再びすべてが正常に機能し始めます。

このページにはどの時点でもエラーが 1 つも表示されません。また、マーカーの位置の自動更新は、ページの存続期間を通じて正常に機能することを追加する必要があります。

フォーラムで見つけたものはすべて試しました。同様に、私はjson応答から応答に移動しましたxml(dom)XMLHttpRequestGET リクエストはデータを自動キャッシュする傾向があるため、メソッドを変更してみました。しかし、何も私を助けませんでした。私は完全に無知です、何が間違っているのか、自分のコードで何をしているのか。

ここに私のJavaScriptコードがあります:

    <script type="text/javascript">
    var map;
var contentString = "";
var infoWindow = new google.maps.InfoWindow({content: contentString});
var url = "genAjaxResponse.php?id=<?php echo $id; ?>";
var marker;
var gmarkers = new Array();
var icon;

var lastClickedMarker;
var stImgId;

var customIcons = {
  Moving: {
    icon: 'icons/abc.png'
  },
  Idle: {
    icon: 'icons/xyz.png'
  },
  Parked: {
    icon: 'icons/pqr.png'
  },
  Alert: {
    icon: 'icons/wxy.png'
  }
};

function load() {  // to be called on onload event of body
  map = new google.maps.Map(document.getElementById("map"), {           
        zoom: 6,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        scaleControl: true,
        center:new google.maps.LatLng(15.570128,78.957092)
  });


  calldownloadUrl(url,map,infoWindow);

  directionsDisplay = new google.maps.DirectionsRenderer();
}

function calldownloadUrl(url,map,infoWindow) {
    downloadUrl(url,displayMarker,map,infoWindow);  
}

function displayMarker(data,map,infoWindow) {

    function generateTriggerCallback(object, eventType) {
        return function() {
            google.maps.event.trigger(object, eventType);
        };
    }

var namearr = Array();
    var json = data.responseText;
    var vehicles = eval ("(" + json + ")");

    var i = 0;
    for (var veh in vehicles)
    {
    var tag = vehicles[veh];            
    var veh_no = tag["veh_no"];
        var is_stale = tag["is_stale"];
        var ignition_off = tag["ignition_off"];
        var speed = tag["speed"];
        var lat = tag["lat"];
        var lng = tag["lng"];
        var time = tag["time_stamp"];
        var address = tag["address"];

        var point = new google.maps.LatLng(
            parseFloat(lat),
            parseFloat(lng));
        var type;                 
        var status;

        stImgId = i+1;
        if(ignition_off == 0 && speed > 3) {
            type = "Moving";
            status = type + "(" + speed + " Kmph)"; 
            document.getElementById("img"+stImgId).src = "icons/greenalert2.png";
        }
        else {
            if(ignition_off == 1) {
                type = "Parked";
                status = type;
                document.getElementById("img"+stImgId).src = "icons/greyalert2.png";
            }
            else {
                type = "Idle";
                status = type;
                document.getElementById("img"+stImgId).src = "icons/yellowalert2.png";
            }
        }
        if(is_stale == 1) {
            type = "Alert";
            status = type;
            document.getElementById("img"+stImgId).src = "icons/redalert2.png";
        }                 

        infoWindow.close();

        var icon = customIcons[type] || {};         
        if(typeof gmarkers[i] != 'undefined') { 
            gmarkers[i].setPosition(point); 
            gmarkers[i].setIcon(icon.icon);
            if(gmarkers[i].id == lastClickedMarker)  {
                if(map.getBounds().contains(gmarkers[i].getPosition()) === false)
                    map.setCenter(gmarkers[i].getPosition());
            }                   
        }
        else
        { 
            gmarkers[i] = new google.maps.Marker({ 
                    id: i,
                    position: point,
                    icon: icon.icon,
                    title: veh_no,
                    map: map
            }); 
        }
        var html = "<span><p><b>"+veh_no +"</b></p> <p>Address: "+address+"<br />Status: "+status+"<br />Time: "+time+"</p></span>";

        namearr[i] = "<span><p><b>"+veh_no +"</b></p> <p>Address: "+address+"<br />Status: "+status+"<br />Time: "+time+"</p></span>";

        // -- bind click event to texts (vehicle nos) -- //
        var textclick = document.getElementById(i);
        textclick.onclick = generateTriggerCallback(gmarkers[i],"click");
        // -- bind click event to markers -- //
        bindinfoWindow(gmarkers[i], map, infoWindow, namearr[i], icon);
        i++;
    }
}

function bindinfoWindow(marker, map, infoWindow, html, icon) {
  google.maps.event.addListener(marker, 'click', function() {       
    lastClickedMarker = marker.id;
    map.setCenter(marker.getPosition());
    if(map.zoom < 15)
        map.setZoom(15);        
    marker.setIcon(icon.icon);        
    marker.setZIndex(google.maps.Marker.MAX_ZINDEX + 1);        
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
}

function downloadUrl(url, callback, map, infoWindow) {
  var request = window.ActiveXObject ?
      new ActiveXObject('Microsoft.XMLHTTP') :
      new XMLHttpRequest;

  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      request.onreadystatechange = doNothing;
      callback(request, map, infoWindow, request.status);
    }
  };

  request.open('GET', url, true);
  request.send();
}

function doNothing() {}

window.setInterval(function() {calldownloadUrl(url,map,infoWindow)},20000);
</script>
4

2 に答える 2

0

gmarkersそのajaxリクエストを呼び出すたびに配列を空にするかi、受信したデータを処理する前に変数をリセットする必要があると思います。このようにして、以前のマーカーにすべての新しいマーカーを追加しているわけではありません。これがコードのボトルネックのようです。

PS私はあなたのコードをテストしませんでした。推測しているだけです。

于 2013-02-02T12:52:36.217 に答える
0

私は同様のアプリを持っていますが、同様の動作にも遭遇しました。私の場合、30 秒ごとにマーカーの配列を更新しています (マーカーごとに: 場所、アイコン、リスナーのコンテンツ)。

まず、更新ごとに新しいマーカーを作成するのをやめましたmarkers[id].setMap(null);.CGがこれを処理することを設定して新しいマーカーを作成しても問題ないと思いました。

次に、次のように、マーカーの位置、アイコン、リスナーのみを更新するようにコードを変更しました。

 this.markers[id].setPosition(new google.maps.LatLng(lat, lng));
 this.markers[id].setIcon(this.updateFlags(status, id));

 google.maps.event.addListener(this.markers[id], 'mouseover', function () {
     infoWindow.setContent(text);
     infoWindow.open(this.map, this);
 });

 google.maps.event.addListener(this.markers[id], 'click', function () {
     devices.selectDevice(index);
 });

これにより、消費されるメモリがはるかに少なくなりましたが、それでも...

最後に、次のようにコードを編集しました。

 this.markers[id].setPosition(new google.maps.LatLng(lat, lng));
 this.markers[id].setIcon(this.updateFlags(status, id));

 google.maps.event.clearListeners(this.markers[id], 'mouseover');
 google.maps.event.clearListeners(this.markers[id], 'click');

 google.maps.event.addListener(this.markers[id], 'mouseover', function () {
     infoWindow.setContent(text);
     infoWindow.open(this.map, this);
 });

 google.maps.event.addListener(this.markers[id], 'click', function () {
     devices.selectDevice(index);
 });

Chrome Developer Tools (F12) -> ProfilerおよびTake Heap Snapshotでテストしました。そして、成長が速すぎるかどうかがわかります。

したがって、あなたの場合、この行を関数 bindinfoWindow() の最初の行として追加することを意味します。

google.maps.event.clearListeners(marker, 'click');
于 2014-01-27T15:39:53.380 に答える