Search code examples
javascriptasynchronouspromisegeocode

JavaScript Promise not executing .then()


I was having some problem with Promise in JavaScript. What I am trying to do is I got a list of address, then for each address, I need to call the geocode API to get the lat lng, then I will proceed to plot the markers together with the heatmap. Here is my code:

let promiseKey = Promise.all(
          result.map()
        );

        var addedMarkers = promiseKey.then(
        markers => Promise.all(
          markers.map()
        )
        )
        .then(drawForecastHeatmap);

The part where I call the geocode API:

function getBranchLatLng(address, branchName, total, queKey){
return new Promise(function(resolve){
    var key = jQuery.rand(geoCodKeys);
    var url = 'https://maps.googleapis.com/maps/api/geocode/json?key='+key+'&address='+address+'&sensor=false';

    $.ajaxq (qyName, {
        url: url,
        dataType: 'json'
    }).done(function( data ) {
        var address = getParameterByName('address', this.url);
        var index = errorArray.indexOf(address);
        try{
            var p = data.results[0].geometry.location;
            var latlng = new google.maps.LatLng(p.lat, p.lng);

            var markerItem =
                {
                    'lat': p.lat,
                    'lng': p.lng,
                    'address': address,
                    'branchName': branchName,
                    'total': total,
                };
            console.log(markerItem);
            resolve(markerItem);

            if (index > -1) {
                errorArray.splice(index, 1);
            }
        }catch(e){
            if(data.status = 'ZERO_RESULTS')
                return false;

            //on error call add marker function for same address and keep in Error ajax queue
            getBranchLatLng( address, 'Error' );
            if (index == -1) {
                errorArray.push( address );
            }
        }
    });

    //mentain ajax queue set
    queuCounter++;
    if( queuCounter == setLimit ){
        queuCounter = 0;
    }

});
}

The problem now is, the program just stopped at getBranchLatLng() and never even go into the addForecastMarker() although I managed to print out some lat lng from geocode.

Some of the address returning me:

jquery.min.js:4 GET https://maps.googleapis.com/maps/api/geocode/json?key=&address= 400 ()

Then when I try to extend the link, I am getting this:

error_message: "Invalid request. Missing the 'address', 'bounds', 'components', 'latlng' or 'place_id' parameter."
results :[]
status: "INVALID_REQUEST"

Any ideas on how to resolve those address with 'INVALID_REQUEST' back to the Promise parent?

Thanks!


Solution

  • It is not possible to generate the working code without having all the test data and undeclared variable that you are using in your code. But overall what I can suggest is that, you must add a catch block to the ajax request, and keep into mind that there must be no workflow in your getBranchLatLng Promise that is not resolving or rejecting the promise.

    Assuming that, incase of any error, you still want to resolve your getBranchLatLng, I have updated your code like this, so that there are no workflow in your getBranchLatLng promise that won't resolve or reject

    let promiseKey = Promise.all(
              result.map(el=>getBranchLatLng(el.branchAddress, el.branchName, el.amount))
            );
    
            var addedMarkers = promiseKey.then(
            markers => Promise.all(
              markers.map(marker => addForecastMarker(marker))
            )
            )
            .then(drawForecastHeatmap)
            .catch(functon(e) {
                //Do the error handling here
            });
    
    function getBranchLatLng(address, branchName, total, queKey) {
    return new Promise(function(resolve, reject) {
        var key = jQuery.rand(geoCodKeys);
        var url = 'https://maps.googleapis.com/maps/api/geocode/json?key='+key+'&address='+address+'&sensor=false';
    
        var qyName = '';
        if( queKey ) {
            qyName = queKey;
        } else {
            qyName = 'MyQueue'+queuCounter;
        }
    
        $.ajaxq (qyName, {
            url: url,
            dataType: 'json'
        }).done(function( data ) {
            var address = getParameterByName('address', this.url);
            var index = errorArray.indexOf(address);
            try{
                var p = data.results[0].geometry.location;
                var latlng = new google.maps.LatLng(p.lat, p.lng);
    
                var markerItem =
                    {
                        'lat': p.lat,
                        'lng': p.lng,
                        'address': address,
                        'branchName': branchName,
                        'total': total,
                    };
                console.log(markerItem);
                if (index > -1) {
                    errorArray.splice(index, 1);
                }
                resolve(markerItem);
    
            }catch(e) {
                    if (index == -1) {
                    errorArray.push( address );
                }
                    resolve({type: 'error', status: data.status});
    
            }
        })
        .catch(function(e) {
            resolve({type: 'error', status: data.status});
          //Instead of resolving with error code you can also reject the promise
          //reject(e);
        });
    
        //mentain ajax queue set
        queuCounter++;
        if( queuCounter == setLimit ){
            queuCounter = 0;
        }
    
      }
    )};
    
    function addForecastMarker(marker) {
    console.log('adddddd markerssssss');
    }
    

    But this is not the Boilerplate code that you can use to directly get the final result. You need to add the error handling code when the any of the promise would fail. For your help, I have resolved those promises with type: 'error'. Inside the then block of promiseKey you must read those and do further error handling and remove those from the array before calling addForecastMarker over it.

    Hope that it helps.