Search code examples
javascriptasynchronousgoogle-maps-api-3promise

Problem with javascript Promise that never resolves


I created two custom promises that are identical except for the fact they work on different user inputs. Both promises make use of Google Maps API v-3 classes and methods.

Strange thing is that whenever the first one is called it will never resolve and will always return a reject status. Also, even if it not resolves, the promise code will still execute printing in console several console.log() I put as controls.

So those two are the promises:

var checkingDeparture = new Promise((resolve, reject) => {
    console.log('1. checkingDeparture called');  //first function control
    var newDeparture = '';
    var geocoder = new google.maps.Geocoder();
        
    geocoder.geocode({'address': $('#startTransfer').val()}, (results, status) => {
        console.log('2. checkingDeparture geocoder called');   //second function control
        if(status == google.maps.GeocoderStatus.OK) {
            coordPoint = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());
                
            if(google.maps.geometry.poly.containsLocation(coordPoint, window.venicePolygon)) {
                console.log('3. checkingDeparture containsLocation called');   //third function control
                newDeparture = 'Piazzale Roma, Venezia, VE, Italia';
            }
            else {
                newDeparture = $('#startTransfer').val();
            }
        }
            
        console.log(newDeparture);   //function result control
        resolve(newDeparture);
    });
        
    reject('Sorry there was an error with checkingDeparture promise...');
});
    
var checkingDestination = new Promise((resolve, reject) => {
    console.log('1. checkingDestination called');   //first function control
    var newDestination = '';
    var geocoder = new google.maps.Geocoder();
        
    geocoder.geocode({'address': $('#endTransfer').val()}, (results, status) => {
        console.log('2. checkingDestination geocoder called');   //second function control
        if(status == google.maps.GeocoderStatus.OK) {
            coordPoint = new google.maps.LatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng());
                
            if(google.maps.geometry.poly.containsLocation(coordPoint, window.venicePolygon)) {
                console.log('3. checkingDestination containsLocation called');   //third function control
                newDestination = 'Piazzale Roma, Venezia, VE, Italia';
            }
            else {
                newDestination = $('#endTransfer').val();
            }
        }
            
        console.log(newDestination);   //function result control
        resolve(newDestination);
    });
        
    reject('Sorry there was an error with checkingDestination promise...');
});

And this is where they get called:

var checkedDeparture = checkingDeparture;
var checkedDestination = checkingDestination;
    
Promise.all([checkedDeparture, checkedDestination]).then(() => {
    console.log(checkedDeparture + checkedDestination);   //promise values control
    var request = {
        origin: checkedDeparture,
        destination: checkedDestination,
        travelMode: google.maps.TravelMode.DRIVING,
        unitSystem: google.maps.UnitSystem.METRIC
    };
        
    directionsService.route(request, (result, status) => {
        console.log('4. checking value of origin: ' + request.origin);   //fourth function control
        console.log('5. checking value of destination:' + request.destination);   //fifth function control
        console.log('6. directionsService called');   //sixth function control
        if(status == google.maps.DirectionsStatus.OK) {
            //do things
        }
            
        else {
            directionsDisplay.setDirections({routes: []});
            theMap.setCenter(window.globalCenter);
        }
    });
}).catch(e => {
    console.log(e);
});

I cannot see where the error actually is espcially since checkingDestination seems to resolve properly. Also, as checkingDeparture never resolves (but still executes), all the code part chained with .then() will not be executed.


Solution

  • Your promises are rejected before they are resolved!

    Promises by definition fulfill exactly once (whether its a promise or a rejection), and only the first is accepted. So if you write code like:

    new Promise((resolve, reject) => {
      setTimeout(() => resolve(), 1000)
      reject() // this runs first
    })
    

    it will never resolve, and always reject.

    And that is exactly what you are doing.

    You need to modify your promises to only reject once something went wrong (or after a timeout):

    var checkingDeparture = new Promise((resolve, reject) => {
        // snip
            
        geocoder.geocode({'address': $('#startTransfer').val()}, (results, status) => {
            // snip
            if (status === "error") { // Change this for a real check
              reject('Sorry there was an error with checkingDeparture promise...');
            } else {
               resolve(newDeparture);
            }
        });
            
        
    });