Google Maps Geocode AngularJS忽略了回调

时间:2015-09-10 22:50:00

标签: javascript angularjs google-maps javascript-objects google-geocoder

我对AngularJS中Google地图的JavaScript Geocode Api有一个奇怪的问题。

首先,我做了一些研究,发现我必须使用javascript回调函数从坐标中获取格式化的地址。

我实现了这样的回调函数:

"use strict";

var getParcelApp = angular.module("getParcelApp", []);

function getStartAddress(latlng, callback) {
    var geocoder = new google.maps.Geocoder;

    geocoder.geocode({ 'location': latlng }, function(results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
            callback(results[2].formatted_address); // HERE THE CALLBACK
        }
    });
};

var GetParcelAppController = function($scope, $http) {
    $http.get("/umbraco/surface/ParcelSurface/GetLatLngParcel")
        .success(function(result) {
            $scope.coordinates = result;
            $scope.getStartCoordinate();
        })
        .error(function(data) {
            console.log(data);
        });

    $scope.getStartCoordinate = function() {
        var latlng;

        $scope.listOfCoordinates = [];

        for (var i = 0; i < $scope.coordinates.length; i++) {
            latlng = { lat: $scope.coordinates[i].Latitude, lng: $scope.coordinates[i].Longitude };

            getStartAddress(latlng, function(formattedAddress) {
                console.log(formattedAddress); // HERE formattedAddress WORKS
                var coordinate = {
                    id: $scope.coordinates[i].Id,
                    waypointId: $scope.coordinates[i].WaypointId,
                    latitude: $scope.coordinates[i].Latitude,
                    longitude: $scope.coordinates[i].Longitude,
                    address: formattedAddress // HERE formattedAddress ISN'T WORKING
                };
                $scope.listOfCoordinates.push(coordinate);
            });
        }
        console.log($scope.listOfCoordinates);

    };
};

getParcelApp.controller("getParcelAppCtrl", GetParcelAppController);

正如您所看到的,我想要一个坐标对象数组。但是我真的不知道为什么console.log显示正确的结果并且数组完全为空

Firefox控制台显示以下内容:

  • 数组:
    • Array [] getParcelController.js:45:9
  • 格式化地址:
    • Mitte,Berlin,Deutschland getParcelController.js:34:17
    • Innenstadt,Köln,Deutschland getParcelController.js:34:17
    • Altstadt-Lehel,München,Deutschland getParcelController.js:34:17
    • Mitte,Berlin,Deutschland getParcelController.js:34:17
    • Innenstadt,Köln,Deutschland getParcelController.js:34:17

您是否知道为什么控制台日志工作正常且数组功能不正常? 如果我在回调函数之外编写数组函数而没有地址:,则会创建数组。

更详细:

我想在选择下拉框中显示坐标的格式化地址。这在html文件中定义为

<select id="getParcel" class="form-control"></select>

我编辑了getStartAddress调用,如下所示:

$scope.getStartCoordinate = function() {
    var latlng;
    var selectBox = document.getElementById("getParcel");

    $scope.listOfCoordinates = [];

    for (var i = 0; i < $scope.coordinates.length; i++) {
        latlng = { lat: $scope.coordinates[i].Latitude, lng: $scope.coordinates[i].Longitude };

        getStartAddress(latlng, function(formattedAddress) {
            var coordinate = {
                id: $scope.coordinates[i].Id,
                waypointId: $scope.coordinates[i].WaypointId,
                latitude: $scope.coordinates[i].Latitude,
                longitude: $scope.coordinates[i].Longitude,
                address: formattedAddress
            };
            $scope.listOfCoordinates.push(coordinate);
            console.log($scope.listOfCoordinates);

            var selectElement = document.createElement("option");
            selectElement.textContent = coordinate.address;
            selectElement.value = coordinate.address;

            selectBox.appendChild(selectElement);
        });
    }

};

我真的不是javascript专家,但据我所知,在获取回调数据时会调用getStartAddress中的函数吗? 所以当回调结束时,选择下拉框应填充地址,不是吗?

2 个答案:

答案 0 :(得分:1)

您正在循环中处理异步 google.maps.Geocoder.geocode函数。为此,您可能希望利用$q.all 将一些承诺合并为一个承诺,只有在所有承诺得到解决后才能解决

在您的情况下,让我们首先介绍承诺以获取地址:

$scope.getStartAddressPromise = function (latlng) {
    var deferred = $q.defer();
    getStartAddress(latlng, function (formattedAddress) {
        console.log(formattedAddress); // HERE formattedAddress WORKS
        var coordinate = {
            id: latlng.Id,
            waypointId: latlng.WaypointId,
            latitude: latlng.Latitude,
            longitude: latlng.Longitude,
            address: formattedAddress // HERE formattedAddress ISN'T WORKING
        };
        $scope.listOfCoordinates.push(coordinate);
        deferred.resolve();
    });
    return deferred.promise;
};

然后你可以替换:

for (var i = 0; i < $scope.coordinates.length; i++) {
    latlng = { lat: $scope.coordinates[i].Latitude, lng: $scope.coordinates[i].Longitude };

    getStartAddress(latlng, function (formattedAddress) {
        console.log(formattedAddress); // HERE formattedAddress WORKS
        var coordinate = {
            //id: $scope.coordinates[i].Id,
            //waypointId: $scope.coordinates[i].WaypointId,
            latitude: $scope.coordinates[i].Latitude,
            longitude: $scope.coordinates[i].Longitude,
            address: formattedAddress // HERE formattedAddress ISN'T WORKING
        };
        $scope.listOfCoordinates.push(coordinate);
    });
}
console.log($scope.listOfCoordinates);

使用:

var promises = [];

$scope.listOfCoordinates = [];
angular.forEach($scope.coordinates, function (coordinate) {
    var latlng = { lat: coordinate.Latitude, lng: coordinate.Longitude };
    promises.push($scope.getStartAddressPromise(latlng));
});

$q.all(promises).then(function () {
    console.log($scope.listOfCoordinates);
});

完整示例

Plunker

答案 1 :(得分:0)

好吧,我用forEach解决了这个问题,而不是简单的for循环。

结果如下:

"use strict";

var getParcelApp = angular.module("getParcelApp", []);

function getStartAddress(latlng, callback) {
    var geocoder = new google.maps.Geocoder;

    geocoder.geocode({ 'location': latlng }, function(results, status) {
        if (status === google.maps.GeocoderStatus.OK) {
            callback(results[2].formatted_address);
        }
    });
};

var GetParcelAppController = function($scope, $http) {
    $http.get("/umbraco/surface/ParcelSurface/GetLatLngParcel")
        .success(function(result) {
            $scope.coordinates = result;
            $scope.getStartCoordinate();
        })
        .error(function(data) {
            console.log(data);
        });

    $scope.getStartCoordinate = function() {
        var latlng;
        var selectBox = document.getElementById("getParcel");

        $scope.listOfCoordinates = [];

        $scope.coordinates.forEach(function(point) {
            latlng = { lat: point.Latitude, lng: point.Longitude };

            getStartAddress(latlng, function (formattedAddress) {
                var coordinate = {
                    id: point.Id,
                    waypointId: point.WaypointId,
                    latitude: point.Latitude,
                    longitude: point.Longitude,
                    address: formattedAddress
                };
                $scope.listOfCoordinates.push(coordinate);

                var selectElement = document.createElement("option");
                selectElement.textContent = formattedAddress;
                selectElement.value = formattedAddress;

                selectBox.appendChild(selectElement);
            });
        });
    };
};

getParcelApp.controller("getParcelAppCtrl", GetParcelAppController);