未捕获的TypeError:无法读取未定义

时间:2016-02-29 22:17:03

标签: javascript jquery google-maps google-maps-api-3

我正在尝试使用Google地图javascript API建立一个网站,以查找城市周围的酒店,并比较每个酒店与用户输入位置之间的距离,以便找到离他们想要访问的所有地点最近的酒店

首先,它计算用户输入位置的坐标(使用地理编码API工作正常),然后获取酒店的坐标/谷歌位置信息。

使用google.maps.geometry.spherical.computeDistanceBetween(LatLng a,LatLng b);为了获得每个酒店和用户输入的地址之间的距离,该函数返回此错误:

未捕获的TypeError:无法读取未定义的属性'lat'

但是,我传递给函数的两个LatLng参数似乎都不是null或未定义。

每个if(location1!=“”),if(location2!=“”)等代码块检查酒店或位置的LatLng对象是否为空,如果是,则打印错误,但是当我运行网页时,这些错误打印在javascript控制台中。

以下是相关的Javascript和HTML:

			
			var map;
			var infowindow;

			function initMap() {
			 var pyrmont = {lat: -33.867, lng: 151.195};

			  map = new google.maps.Map(document.getElementById('map'), {
				center: pyrmont,
				zoom: 15
			  });


			  infowindow = new google.maps.InfoWindow();

			}

			

			function createMarker(place) {
			  var placeLoc = place.geometry.location;
			  var marker = new google.maps.Marker({
				map: map,
				position: place.geometry.location
			  });

			  google.maps.event.addListener(marker, 'click', function() {
				infowindow.setContent(place.name);
				infowindow.open(map, this);
			  });
			}
			var nearbyHotels = [];
			var cityCoordinates;
			var cityCoordinatesLatLng;
			function findHotels()
			{
				
				var nearbyHotelsLat = [];
				var nearbyHotelsLong = [];
				
				var locationScores1 = [];
				var locationScores2 = [];
				var locationScores3 = [];
				var locationScores4 = [];
				var locationScores5 = [];
				
				var avgScores = [];

				var geocoder = new google.maps.Geocoder();
				var cityAddress = document.getElementById('locations_cityField').value;
				var radiusSearch = parseInt(document.getElementById('locations_rangeField').value);
				
				var location1 = document.getElementById('locations_location1').value;
				var location2 = document.getElementById('locations_location2').value;
				var location3 = document.getElementById('locations_location3').value;
				var location4 = document.getElementById('locations_location4').value;
				var location5 = document.getElementById('locations_location5').value;
				
				var location1LatLng;
				var location2LatLng;
				var location3LatLng;
				var location4LatLng;
				var location5LatLng;
				
				if(location1 != "" && location1 != undefined)
					location1LatLng = geocodeAddress(geocoder, location1);
					
				if(location2 != "" && location2 != undefined)
					location2LatLng = geocodeAddress(geocoder, location2);
					
				if(location3 != "" && location3 != undefined)
					location3LatLng = geocodeAddress(geocoder, location3);
				
				if(location4 != "" && location4 != undefined)
					location4LatLng = geocodeAddress(geocoder, location4);
					
				if(location5 != "" && location5 != undefined)
					location5LatLng = geocodeAddress(geocoder, location5);

				console.log(location1LatLng);
				
				var cityLoc = geocodeAddress(geocoder, cityAddress);
				setTimeout(function(){
				
					
					var coordSplit = cityCoordinates.split(",");
					
					var lati = parseFloat(coordSplit[0]);
					var lngi = parseFloat(coordSplit[1]);
					
					var city = {lat: lati, lng: lngi};
					
					var service = new google.maps.places.PlacesService(map);
					  service.nearbySearch({
						location: city,
						radius: radiusSearch,
						types: ['lodging']
					  }, callback);
					  
					map.setCenter(cityLoc);
					setTimeout(function(){
						console.log("nearbyHotels.length: " + nearbyHotels.length);
						if(location1 != "")
						{
							for(var i = 0; i < nearbyHotels.length; i++)
							{
							
								var hotelLatLng = nearbyHotels[i].geometry.location;
								
								if(location1LatLng == "")
								{
									console.log("NULL LOCATION1LATLNG");
								}
								if(hotelLatLng == "")
								{
									console.log("NULL (1) HOTELLATLNG");
								}
								var dist = google.maps.geometry.spherical.computeDistanceBetween(location1LatLng, hotelLatLng);
								locationScores1.push(dist);
							}
						}
						if(location2 != "")
						{
							for(var i = 0; i < nearbyHotels.length; i++)
							{
								var hotelLatLng = nearbyHotels[i].geometry.location;
								if(location2LatLng == "")
								{
									console.log("NULL LOCATION2LATLNG");
								}
								if(hotelLatLng == "")
								{
									console.log("NULL (2) HOTELLATLNG");
								}
								var dist = google.maps.geometry.spherical.computeDistanceBetween(location2LatLng, hotelLatLng);
								locationScores2.push(dist);
							}
						}
						if(location3 != "")
						{
							for(var i = 0; i < nearbyHotels.length; i++)
							{
								var hotelLatLng = nearbyHotels[i].geometry.location;
								if(location3LatLng == "")
								{
									console.log("NULL LOCATION3LATLNG");
								}
								if(hotelLatLng == "")
								{
									console.log("NULL (3) HOTELLATLNG");
								}
								var dist = google.maps.geometry.spherical.computeDistanceBetween(location3LatLng, hotelLatLng);
								locationScores3.push(dist);
							}
						}
						if(location4 != "")
						{
							for(var i = 0; i < nearbyHotels.length; i++)
							{
								var hotelLatLng = nearbyHotels[i].geometry.location;
								if(location4LatLng == "")
								{
									console.log("NULL LOCATION4LATLNG");
								}
								if(hotelLatLng == "")
								{
									console.log("NULL (4) HOTELLATLNG");
								}
								var dist = google.maps.geometry.spherical.computeDistanceBetween(location4LatLng, hotelLatLng);
								locationScores4.push(dist);
							}
						}
						if(location5 != "")
						{
							for(var i = 0; i < nearbyHotels.length; i++)
							{
								var hotelLatLng = nearbyHotels[i].geometry.location;
								if(location5LatLng == "")
								{
									console.log("NULL LOCATION5LATLNG");
								}
								if(hotelLatLng == "")
								{
									console.log("NULL (5) HOTELLATLNG");
								}
								var dist = google.maps.geometry.spherical.computeDistanceBetween(location5LatLng, hotelLatLng);
								locationScores5.push(dist);
							}
						}
						
						for(var i = 0; i < nearbyHotels.length; i++)
						{
							var avgDist;
							var numLocations = 0;
							
							if(location1 != "")
							{
								numLocations++;
								avgDist += locationScores1[i];
							}
							if(location2 != "")
							{
								numLocations++;
								avgDist += locationScores2[i];
							}
							if(location3 != "")
							{
								numLocations++;
								avgDist += locationScores3[i];
							}
							if(location4 != "")
							{
								numLocations++;
								avgDist += locationScores4[i];
							}
							if(location5 != "")
							{
								numLocations++;
								avgDist += locationScores5[i];
							}
							
							avgDist = avgDist / numLocations;
							
							avgScores.push(avgDist);
							
							
							
						}
						var avgScoresSorted = avgScores.sort(function (a, b) { 
								return b - a;
							});
							
							
						for(var i = 0; i < avgScoresSorted.length; i++)
						{
							var index = avgScores.indexOf(avgScoresSorted[i]);
							var hotelName = nearbyHotels[index].name;
							var hotelAddress = nearbyHotels[index].vicinity;
							document.getElementById("displayHotelsDiv").innerHTML += (i + 1) + ": " + hotelName + " (" + hotelAddress + ") - LocationScore: " + avgScoresSorted[i];
						}
					}, 10000);
					
				}, 5000);
				
				
      			
			}
			
			function callback(results, status) {
			  if (status === google.maps.places.PlacesServiceStatus.OK) {
				for (var i = 0; i < results.length; i++) {
				  console.log(results[i]);
				  createMarker(results[i]);
				  nearbyHotels.push(results[i]);
				}
			  }
			}
			
			function initSearchButtonListener()
			{
				
				
				document.getElementById('button_searchhotels').addEventListener('click', function() {
					findHotels();
				  });
				  
				initMap();
			}
			
			
			function geocodeAddress(geocoder, address) {
				console.log("address " + address);
				console.log("geocoder " + geocoder);
			  geocoder.geocode({'address': address}, function(results, status) {
				if (status === google.maps.GeocoderStatus.OK) {
					var coords = results[0].geometry.location.toString();
					console.log("CoordsRaw: " + coords)
					var coordsNoFirst = coords.substring(1);
					var coordsNoLast = coordsNoFirst.slice(0, -1);
					cityCoordinates = coordsNoLast;
					console.log(cityCoordinates);
					
					return results[0].geometry.location;
					
				} else {
				  alert('Could not convert an address to latitude/longitude for the google maps API: ' + status);
				}
			  });
			}
		
			
			
			

		

与之相关的HTML:

<div class="container" id="locations">
		    	<div class="row">

		    		<div class="col-md-6">
		    			<input type="text" class="form-control" id="locations_location1" placeholder="Enter address of the 1st location">
		    		</div>
		      		
		   			<div class="col-md-6">
		    			<input type="text" class="form-control" id="locations_location2" placeholder="Enter address of the 2nd location">
		    		</div>
		     	 
		    	</div>
		    	<br></br>
		    	<div class="row">

		    		<div class="col-md-6">
		    			<input type="text" class="form-control" id="locations_location3" placeholder="Enter address of the 3rd location">
		    		</div>
		      		
		   			<div class="col-md-6">
		    			<input type="text" class="form-control" id="locations_location4" placeholder="Enter address of the 4th location">
		    		</div>
		     	 
		    	</div>
		    	<br></br>
		    	<div class="row" style="text-align:center">
		      		
		   			<div class="col-md-6">
		    			<input type="text" class="form-control" id="locations_location5" placeholder="Enter address of the 5th location">
		    		</div>
		     	 
		    	</div>
		    	<br></br>
				<div class="row">
					<div id="locationField">
			      		<input type="text" class="form-control" id="locations_cityField" placeholder="Enter a city" type="text" />
			    	</div>
					<div id="rangeField">
			      		<input type="text" class="form-control" id="locations_rangeField" placeholder="Enter a search radius in meters (from the city center)" type="text" />
			    	</div>
				</div>
				<div style="text-align:center">
					<div id="map" style="width: 800px; height: 400px;"></div>    
				</div>
		    	<button id="button_searchhotels" class="btn btn-success btn-lg">Search</button>



<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBVVnR7yKErwMDd6yC-GzVpRXFvNTtoKhQ&signed_in=true&libraries=places,geometry&callback=initSearchButtonListener"
		        async defer></script>

1 个答案:

答案 0 :(得分:0)

地理编码器是异步的,您无法从其回调函数返回任何内容。当/可用时,您必须使用回调函数内的数据。重复How do I return the response from an asynchronous call?

这是不正确的:

function geocodeAddress(geocoder, address) {
  console.log("address " + address);
  console.log("geocoder " + geocoder);
  geocoder.geocode({
    'address': address
  }, function(results, status) {
    if (status === google.maps.GeocoderStatus.OK) {
      var coords = results[0].geometry.location.toString();
      console.log("CoordsRaw: " + coords)
      var coordsNoFirst = coords.substring(1);
      var coordsNoLast = coordsNoFirst.slice(0, -1);
      cityCoordinates = coordsNoLast;
      console.log(cityCoordinates);

      //*********** this will not do anything useful **********
      return results[0].geometry.location;
      //*******************************************************

    } else {
      alert('Could not convert an address to latitude/longitude for the google maps API: ' + status);
    }
  });
}