异步谷歌地图抛弃Javascript - 回调如何工作?

时间:2013-07-17 00:06:31

标签: javascript ajax google-maps

我正在尝试重构一些代码,并尝试使用Google地图来计算经度和纬度。我特意遇到谷歌地图的问题,以获取数据ascynronously。有人很好地提出了一个解决方案,但几天之后,我必须得出结论,我很遗憾地让一个JS新手太过分了。这是整个代码,以及我原来的问题:Asynchronous Google Maps request throwing off Javascript我确定它很小,但我已经尝试了2天而无法获得正常工作的版本。任何帮助都会非常感激 - 我觉得它很小,但是无法理解那是什么。

<script type="text/javascript">
   //declare variables
  var map;
  var directionsService;
  var directionsDisplay1, directionsDisplay2, directionsDisplay3;
  var markersArray = [];
  var stations;

  var autocomplete_options = {componentRestrictions: {country: 'us'}};
  var places = new Array();
  places[0] = "Barlays Center, Brooklyn NY";
  places[1] = "Union Square, nyc";

//formerly var autocomplete_start = new google.maps.places.Autocomplete(document.getElementById("id_start"), autocomplete_options);
    var autocomplete_start = places[0];
//var autocomplete_start = new google.maps.places.PlacesService(places[0]);
    var autocomplete_end = places[1];

  //Figure out the distance between your location and the nearest Citibike station
function getDistance(lat1,lng1,lat2,lng2) {
  var i = lat1 - lat2;
  var j = lng1 - lng2;
  return i*i + j*j;
}

function findNearestStation(lat,lng) {
  var min_distance = 99999;
  var closest_station_id;
  $.each(stations.stationBeanList, function(i, station) {
    var distance = getDistance(lat,lng, station.latitude, station.longitude);

    if (distance < min_distance) {
      min_distance = distance;
      closest_station_id = i;
    }
  });

  console.log('Closest station idx: ' + closest_station_id);

  return stations.stationBeanList[closest_station_id];
}
 //Draw on the map
function drawMarker(lat, lng, map, title, marker_text) {
  var point = new google.maps.LatLng(lat, lng);

  var marker = new google.maps.Marker({
    position : point,
    map : map,
    title : title,
    icon: 'http://chart.apis.google.com/chartchst=d_map_pin_letter&chld='+marker_text+'|FE6256|000000'
  });

  markersArray.push(marker);
}


function clearMarkers() {
  for (var i = 0; i < markersArray.length; i++ ) {
    markersArray[i].setMap(null);
  }
  markersArray = [];
}

function drawMap() {
  var center = new google.maps.LatLng(40.704066,-73.992727);
  var mapOptions = {
    mapTypeId: google.maps.MapTypeId.ROADMAP,
    mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU },
    zoom: 14,
    center: center
  };

  map = new google.maps.Map(document.getElementById("map"), mapOptions);
  directionsService = new google.maps.DirectionsService();
  directionsDisplay1 = new google.maps.DirectionsRenderer();
  directionsDisplay1.setMap(map);
  directionsDisplay1.setPanel(document.getElementById("directions-panel1"));
  directionsDisplay2 = new google.maps.DirectionsRenderer();
  directionsDisplay2.setMap(map);
  directionsDisplay2.setPanel(document.getElementById("directions-panel2"));
  directionsDisplay3 = new google.maps.DirectionsRenderer();
  directionsDisplay3.setMap(map);
  directionsDisplay3.setPanel(document.getElementById("directions-panel3"));

  $.getJSON('./static/js/stations.json', function(data) {
    stations = data;
    var bounds = new google.maps.LatLngBounds();
    $.each(data.stationBeanList, function(i, station) {
      if (station.statusValue == 'In Service') {
        var point = new google.maps.LatLng(station.latitude, station.longitude);
        bounds.extend(point);
      }
    });
    map.setCenter(bounds.getCenter(), map.fitBounds(bounds));
    autocomplete_start.bindTo('bounds', map);
    autocomplete_end.bindTo('bounds', map);
  });
}

$(document).ready(function(){
  drawMap();
});

$('#btn-reset').click(function(){
  $('#directions-panel1').empty();
  $('#directions-panel2').empty();
  $('#directions-panel3').empty();
  $('#directions-info1').empty();
  $('#directions-info2').empty();
  $('#directions-info3').empty();
  drawMap();
});

$('#btn-get-directions').click(function(){
  //take directions on the map

  var start = autocomplete_start;
  var end   = autocomplete_end;
  var start_lat=getLat(start);
  //this is legacy code - the original had Google autocomplete
  var start_lng;
  var end_lat;
  var end_lng;
 // getLat(start);


  function getLat(loc) {
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({'address': loc}, function postcodesearch(results, status) 
    {   
      if (status == google.maps.GeocoderStatus.OK) 
    {
      var lat = results[0].geometry.location.lat();
      //alert(lat);
      return lat;

      //alert(start_lng);
    }
  else {
    alert("Error");
  }
  });
 }
//These are original functions I wrote
function getLng(loc) {
var geocoder_lng = new google.maps.Geocoder();
  geocoder_lng.geocode({'address': loc}, function postcodesearch(results, status) 
{   
  if (status == google.maps.GeocoderStatus.OK) 
{
  var lng = results[0].geometry.location.lng();
 // alert(lng);
  return lng;
  //alert(end_lat);

  //doRest();
}
  else {
     alert("Error");
   }
});
}

//This is a far superior function someone else wrote, which I cannot implement
 function getLatLng(loc, callback) {

    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({'address': loc}, function postcodesearch(results, status) 
  {  
    if (status == google.maps.GeocoderStatus.OK) 
    {
        var lat = results[0].geometry.location.lat();
        var lng = results[0].geometry.location.lng();
        alert("234234");
        return(lat, lng);
    }
   }
  );}

getLatLng(start);
doRest()
 //This is the rest of the code
  function doRest(){

  //var start_lat = start.geometry.location.lat();
  //alert("DO REST");

  var start_lng = getLng(start);
  alert(start_lng);
  var start_p = new google.maps.LatLng(getLatLng(start));
  //alert(start_p);
  //alert(start_p);
  //var end_lat = end.geometry.location.lat();
  //var end_lng = end.geometry.location.lng();
  var end_p = new google.maps.LatLng(getLatLng(end));



  var start_station = findNearestStation(start_p);
  var end_station = findNearestStation(end_p);

  alert("asdf");
  var start_station_p = new google.maps.LatLng(start_station.latitude, start_station.longitude);
  alert("wtf");
  var end_station_p = new google.maps.LatLng(end_station.latitude, end_station.longitude);
  // alert("stations");

  var dir_bounds = new google.maps.LatLngBounds();
  dir_bounds.extend(start_p);
  dir_bounds.extend(end_p);
  dir_bounds.extend(start_station_p);
  dir_bounds.extend(end_station_p);

  drawMarker(start_lat, start_lng, map, $('#id_start').val(), '1');
  drawMarker(start_station.latitude, start_station.longitude, map, start_station.stationName, '2');
  drawMarker(end_station.latitude, end_station.longitude, map, end_station.stationName, '3');
  drawMarker(end_lat, end_lng, map, $('#id_end').val(), '4');
}

  // We'll make 3 calls, 1) walking, 2) biking, 3) walking
  // Walk from start to station 1
  var request1 = {
    origin:start_p,
    destination:start_station_p,
    travelMode: google.maps.TravelMode.WALKING
  };
  directionsService.route(request1, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      $('#directions-info1').html('Walk from ' + $('#id_start').val() + ' to station at ' + start_station.stationName);
      directionsDisplay1.setDirections(result);
    }
  });

  // Bike from station 1 to station 2
  var request2 = {
    origin:start_station_p,
    destination:end_station_p,
    travelMode: google.maps.TravelMode.BICYCLING
  };
  directionsService.route(request2, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      $('#directions-info2').html('Bike from station at ' + start_station.stationName + ' to station at ' + end_station.stationName);
      directionsDisplay2.setDirections(result);
    }
  });

  // Walk from station 2 to end
  var request3 = {
    origin:end_station_p,
    destination:end_p,
    travelMode: google.maps.TravelMode.WALKING
  };
  directionsService.route(request3, function(result, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      $('#directions-info3').html('Walk from station at ' + end_station.stationName + ' to ' + $('#id_end').val() );
      directionsDisplay3.setDirections(result);
    }
  });

  google.maps.event.addListener(directionsDisplay1, 'directions_changed', function() {
    map.setCenter(dir_bounds.getCenter(), map.fitBounds(dir_bounds));
  });
  google.maps.event.addListener(directionsDisplay2, 'directions_changed', function() {
    map.setCenter(dir_bounds.getCenter(), map.fitBounds(dir_bounds));
  });
  google.maps.event.addListener(directionsDisplay3, 'directions_changed', function() {
    map.setCenter(dir_bounds.getCenter(), map.fitBounds(dir_bounds));
  });
});

1 个答案:

答案 0 :(得分:1)

我看到的主要问题是你试图从getlatLng返回值 - 这是行不通的,因为地理编码调用是异步的。关键是使用回调。而不是这样做:

function getLatLng() {
    return somevalue;
}
latlng = getLatLng();
// do something

请改为:

function getLatLng(callback) {
    callback(somevalue);
}
getLatLng(function(latlng) {
    // do something
});

这是getLatLng的实现,它采用开始,结束和回调。反过来,回调是一个带有四个参数的函数:start_lat,start_lng,end_lat,end_lng。它没有检查语法,但希望它有所帮助。

function getLatLng(start, end, callback) {
    var geocoder = new google.maps.Geocoder();

    // geocode the start
    geocoder.geocode({'address': start}, function(results, status) {  
        if (status == google.maps.GeocoderStatus.OK) {
            var startlat = results[0].geometry.location.lat();
            var startlng = results[0].geometry.location.lng();
            console.log('Got start: ' + startlat + ', ' + startlng);

            // geocode the end
            geocoder.geocode({'address': end}, function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    var endlat = results[0].geometry.location.lat();
                    var endlng = results[0].geometry.location.lng();
                    console.log('Got end: ' + endlat + ', ' + endlng);

                    // invoke the callback function
                    callback(startlat, startlng, endlat, endlng);
                }
            });
       }
    });
}

// the third parameter provided here to getLatLng is the callback function:
getLatLng(start, end, function(start_lat, start_lng, end_lat, end_lng) {
    //This is the rest of the code
    var start_p = new google.maps.LatLng(start_lat, start_lng);
    var end_p = new google.maps.LatLng(end_lat, end_lng);
    var start_station = findNearestStation(start_p);
    var end_station = findNearestStation(end_p);
    // etc
});

注意作为一般提示,请使用浏览器的调试工具(Chrome中的Shift-Ctl-J)。这应该允许你:

  1. 检查控制台中的Javascript错误
  2. 将“console.log”语句添加到您的代码中以帮助跟踪其进度
  3. 向代码添加断点以使您能够跟踪其执行情况