【问题标题】:geocoder call does not work in for loop地理编码器调用在 for 循环中不起作用
【发布时间】:2015-05-20 05:21:25
【问题描述】:

我正在研究跟踪多个设备及其最后位置地址、名称、时间等的项目。为了显示地址,我正在使用反向地理编码(Last location lat long 来自 mysql db)。代码适用于单个设备跟踪,但是当我尝试一次显示所有设备时,它只显示第一个设备地址。之后,for 循环停止。我不知道我错在哪里。指出我的错误,如果有人知道,请纠正我。这是我的完整 JavaScript 代码。

<script type="text/javascript">    
function load() {
            var abc;
            var pqr;
            function getLocation() {
                navigator.geolocation.getCurrentPosition(showPosition);
            }
            function showPosition(position) {
                abc = position.coords.latitude;
                pqr = position.coords.longitude;
                googlemap(abc, pqr);
            }
            getLocation();
        }

        function googlemap(lat, lng) {
            var x = document.getElementById("myForm");
            var text = '';
            for (var k = 0; k < x.length; k++) {
                text += x[k].value;
                if (k != (x.length - 1)) {
                    text += ",";
                }
            }

            var names = new Array();
            var colors = new Array();
            var imeis = new Array();
            var times = new Array();
            var point;

            var map = new google.maps.Map(document.getElementById("map"), {
                center: new google.maps.LatLng(lat, lng),
                zoom: 6,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            });

            var iconsetngs = {
                path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW
            };

            setInterval(function () {
                downloadUrl("points.php?data=" + text, function (data) {
                    var xml = data.responseXML;
                    var points = xml.documentElement.getElementsByTagName("point");
                    flightPlanCoordinates = new Array();
                    var imo = '';
                    var w = -1;
                    for (var i = 0; i < points.length; i++) {
                        if (parseFloat(points[i].getAttribute("imei")) != imo) {
                            names.push(points[i].getAttribute("name"));
                            times.push(points[i].getAttribute("time"));
                            colors.push(points[i].getAttribute("color"));
                            imeis.push(parseFloat(points[i].getAttribute("imei")));
                            imo = parseFloat(points[i].getAttribute("imei"));
                            w++;
                            flightPlanCoordinates[w] = new Array();
                        }
                        point = new google.maps.LatLng(
                                parseFloat(points[i].getAttribute("lat")),
                                parseFloat(points[i].getAttribute("lon"))
                                );
                        flightPlanCoordinates[w].push(point);
                    }

                    for (var j = 0; j < imeis.length; j++) {
                        var flightPath = new google.maps.Polyline({
                            path: flightPlanCoordinates[j],
                            geodesic: true,
                            strokeColor: colors[j],
                            strokeOpacity: 1.0,
                            strokeWeight: 2,
                            icons: [{
                                    icon: iconsetngs,
                                    repeat: '35px',
                                    offset: '100%'}]
                        });

                        var geocoder = new google.maps.Geocoder();
                        geocoder.geocode({'latLng': flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1]}, function (results, status) {
                            if (status == google.maps.GeocoderStatus.OK) {
                                if (results[1]) {
                                    map.setZoom(7);
                                    var marker = new google.maps.Marker({
                                        position: flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1],
                                        map: map
                                    });
                                    var contentString = names[j] + times[j] + results[1].formatted_address;
                                    var infowindow = new google.maps.InfoWindow({
                                        content: contentString
                                    });
                                    infowindow.open(map, marker);
                                } else {
                                    alert('No results found');
                                }
                            } else {
                                alert('Geocoder failed due to: ' + status);
                            }
                        });

                        flightPath.setMap(map);
                        geocoder.setMap(map);

                    }
                });
                names = [];
                imeis = [];
                times = [];
                colors = [];
                flightPlanCoordinates = [];
            }, 10 * 1000);
        }


        function downloadUrl(url, callback) {
            var request = window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest;
            request.onreadystatechange = function () {
                if (request.readyState == 4) {
                    request.onreadystatechange = doNothing;
                    callback(request, request.status);
                }
            };
            request.open('GET', url, true);
            request.send(null);
        }

        function doNothing() {
        }    </script>
<body onload="load();">
    <form method="post" id="myForm" class="myForm" name="myForm">
        <select name="dvc">
            <option value="all">All</option>
            <?php
            $qry = mysql_query("SELECT * FROM devices");
            while ($row = mysql_fetch_array($qry)) {
                ?>
                <option value="<?php echo $row['device_imei']; ?>"><?php echo $row['device_name']; ?></option>
            <?php } ?>
        </select>
        <input type="date" name="exct" value="<?php echo $date; ?>"/>
        From:
        <input type="date" name="from" />
        To:
        <input type="date" name="to" />
    </form>
    <button onclick="load();">Submit</button>

    <div id="map" style="width: 100%; height: 100%"></div>
</body>

【问题讨论】:

  • 能否也发布一些 HTML 和一些示例数据?我在您的代码中看不到任何实际错误(尽管您的某些选择让我有些困惑),但如果有一些可运行的代码(可能是 sn-p 或指向 jsFiddle 示例的链接),它会有所帮助。跨度>
  • @stackoverflow.com/users/2020820/steve-k 我也编辑了我的 HTML 代码。而且 mysql 数据来自 XML
  • @Steve K 我的代码有错误吗?如果不是,那么为什么它在 geocoder.setMap(map); 之后不起作用陈述。在该语句之后,它不会在 for 循环中 for j=1(imeis.length 为 2)。
  • 您的代码中可能存在错误:竞争条件。回调不会同步执行。因此,您的回调已注册,但当它们全部执行时,j 将是其最大值,您只需一遍又一遍地进行相同的调用。
  • 如果你能建议我解决这个问题(更改代码),这对我有好处。

标签: javascript google-maps reverse-geocoding


【解决方案1】:

当前的变量取决于回调执行时j 的值,这可能要等到实际的for 循环结束并且j 达到其最大值时才会发生。相反,您需要使它们拥有自己的范围。 Javascript 没有块作用域,因此您需要将其包装在另一个函数调用中,如下所示:

var createGeocodeCallback = function(n){
    return function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            if (results[1]) {
                map.setZoom(7);
                var marker = new google.maps.Marker({
                    position: flightPlanCoordinates[n][(flightPlanCoordinates[n].length) - 1],
                    map: map
                });
                var contentString = names[n] + times[n] + results[n].formatted_address;
                var infowindow = new google.maps.InfoWindow({
                    content: contentString
                });
                infowindow.open(map, marker);
            } else {
                alert('No results found');
            }
        } else {
            alert('Geocoder failed due to: ' + status);
        }
    };
}

然后在你的 googlemap() 函数的第二个循环中,你可以这样做:

for (var j = 0; j < imeis.length; j++) {
    var flightPath = new google.maps.Polyline({
        path: flightPlanCoordinates[j],
        geodesic: true,
        strokeColor: colors[j],
        strokeOpacity: 1.0,
        strokeWeight: 2,
        icons: [{
                icon: iconsetngs,
                repeat: '35px',
                offset: '100%'}]
    });

    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({'latLng': flightPlanCoordinates[j][(flightPlanCoordinates[j].length) - 1]}, createGeocodeCallback(j));

    flightPath.setMap(map);
    geocoder.setMap(map);

}

将数据存储为要处理的一组对象(并访问item.nameitem.timeitem.flightPlanCoordinates 等)可能会更容易、更清晰,因此您可以使用@987654330 创建回调@ 它会为您处理整个范围界定的事情。

【讨论】:

  • 成功了。谢谢您的建议。所有问题都是由于 geocoder.setMap(map);陈述。没有任何必要。那句话是错误的。所以 Javascript 不再从那里执行。
  • 如何处理这段代码中的OVER QUERY LIMIT问题?我唯一知道的是我必须在 if (status == google.maps.GeocoderStatus.OK) 的其他部分做一些事情。但是该怎么办呢?
猜你喜欢
  • 2017-11-01
  • 2015-07-04
  • 2012-01-17
  • 2022-12-10
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
相关资源
最近更新 更多