我对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控制台显示以下内容:
您是否知道为什么控制台日志工作正常且数组功能不正常? 如果我在回调函数之外编写数组函数而没有地址:,则会创建数组。
更详细:
我想在选择下拉框中显示坐标的格式化地址。这在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中的函数吗? 所以当回调结束时,选择下拉框应填充地址,不是吗?
答案 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);
});
完整示例
答案 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);