Search code examples
javascriptjquerygoogle-mapses6-promise

Local scope object sometimes works within a javascript promise with .then


Hoping someone out there can offer an incline of insight/advice on how to overcome my coding issue?

I am trying to update a global scope object var, locally within a Promise.then() function. The data comes from an element in the DOM which has been manipulated inside another function as part of the $.when procedure.

Inside the .then() I can console.log the element and verify that the element has been updated and is such within the local scope, but when I try to pass that data to "placeIDs" object and console.log that it sometimes works and sometimes shows as undefined.

It, to me seems to have defied normal logic unless my brain is cooked and I am not seeing the obvious.

My code is below (it is all part of a Google maps API script), please ask if you need any answers in order to help, good luck and thank you.

  var target   = null,
      placeIDs = {

          originPlaceId:      null,
          destinationPlaceId: null

      }
  ;

  // Render the direction route for the map
  $.when(calculateAndDisplayRoute(map, me, directionsService, directionsDisplay)).then(function(response) {

    const target = $('.site-content');

    const placeIDs = {

      originPlaceId:      target.attr('data-orig'),
      destinationPlaceId: target.attr('data-dest')

    }

    // Add the autocomplete function for the map
    new AutocompleteDirectionsHandler(map, directionsService, directionsDisplay, placeIDs.originPlaceId, placeIDs.destinationPlaceId);

  }).catch(

    (reason) => {

      // Log the rejection reason
      console.log('Handle rejected ' + reason + ' promise.');

  });

As requested the promise function below:

function calculateAndDisplayRoute(map, me, directionsService, directionsDisplay) {

    if (me == null) {

        var travelModeChosen = 'DRIVING';

    } else {

        var travelModeChosen = me.travelMode;

    }

    placeIDs = directionsService.route({

        origin:       document.getElementById('origin-input').value,
        destination:  document.getElementById('destination-input').value,
        travelMode:   travelModeChosen

    }, function(response, status) {

        if (status === 'OK') {

            // Clear the direction text panel
            $('#right-panel').empty();

            // Insert place IDs into the DOM
            $('.site-content')
                .attr('data-orig', response.geocoded_waypoints[0]['place_id'])
                .attr('data-dest', response.geocoded_waypoints[1]['place_id'])
            ;

            directionsDisplay.setPanel(document.getElementById('right-panel'));
            directionsDisplay.setDirections(response);

            if (travelModeChosen == 'DRIVING') {

                var trafficLayer = new google.maps.TrafficLayer();
                trafficLayer.setMap(map);

            } else if (travelModeChosen == 'TRANSIT') {

                var transitLayer = new google.maps.TransitLayer();
                transitLayer.setMap(map);

            } else if (travelModeChosen == 'BYCYCLE') {

                var bikeLayer = new google.maps.BicyclingLayer();
                bikeLayer.setMap(map);

            }

            // Set up the map for the direction route and pins
            directionsDisplay.setMap(null);
            directionsDisplay.setMap(map);

        } else {

            window.alert('Directions request failed due to ' + status);

        }

    });

}

Solution

  • As requested in comments, please let me know if you need help. I'd advice you to read into promises or at least watch the video to understand why, the how gets easier when you understand why JS uses promises:

    function calculateAndDisplayRoute(map, me, directionsService, directionsDisplay) {
      const travelModeChosen = (me||{}).travelMode || "DRIVING";
    
      return new Promise(
        (resolve,reject)=>
          directionsService.route(
            {
              origin: document.getElementById('origin-input').value,
              destination: document.getElementById('destination-input').value,
              travelMode: travelModeChosen
            }
            ,(response,status)=>
              status==="OK"
                ? resolve(response)
                : reject(status)
          )
    
      )
      .then(
        response => {
          $('#right-panel').empty();
    
          // Insert place IDs into the DOM
          $('.site-content')
            .attr('data-orig', response.geocoded_waypoints[0]['place_id'])
            .attr('data-dest', response.geocoded_waypoints[1]['place_id'])
            ;
    
          directionsDisplay.setPanel(document.getElementById('right-panel'));
          directionsDisplay.setDirections(response);
    
          if (travelModeChosen == 'DRIVING') {
    
            var trafficLayer = new google.maps.TrafficLayer();
            trafficLayer.setMap(map);
    
          } else if (travelModeChosen == 'TRANSIT') {
    
            var transitLayer = new google.maps.TransitLayer();
            transitLayer.setMap(map);
    
          } else if (travelModeChosen == 'BYCYCLE') {
    
            var bikeLayer = new google.maps.BicyclingLayer();
            bikeLayer.setMap(map);
    
          }
    
          // Set up the map for the direction route and pins
          directionsDisplay.setMap(null);
          directionsDisplay.setMap(map);
        }
        ,reject =>
          window.alert('Directions request failed due to ' + reject)
      )
    
    }