0

I need to processing list of data via HERE Map geocoder, for convert locationId to coordinates. geocoder class has geocode function that take 3 arguments 1 parameter 2. successCallFunction 3. failCallFunction.

  self.geocodeByLocationIdByArray = function (locationIds, callback)
            {
                var deferred = $.Deferred();
                var result = []; 

                var convert = function () {
                    for (var i = 0; i < locationIds.length - 1; i++)
                    {
                        geocodingParameters = {
                            locationId: locationIds[i].locationId;
                        };
                        self.geocoder.geocoder(geocodingParameters, onGeocodeSuccess, function () { });
                    }

                };

                convert();
                return deferred.promise();
            };

 onGeocodeSuccess = function (result) {

                var locations = result.Response.View[0].Result,
                    i;
                var result = [];
                // Add a marker for each location found
                for (i = 0; i < locations.length; i++) {
                    result.push(new geoCoordinate(locations[i].Location.DisplayPosition.Latitude, locations[i].Location.DisplayPosition.Longitude));
                }

                return result;
            };

How to fix geocodeByLocationIdByArray function for wait until all data is preceded and return result array ? I am a little bit stop on it :( my problem is that geocoder is async.

Arbejdsglæde
  • 13,670
  • 26
  • 78
  • 144
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Heretic Monkey Apr 06 '17 at 22:09
  • you can't, because it's async. it looks like you're passing in a callback function, why not call that function once you get your results? – Heretic Monkey Apr 06 '17 at 22:10
  • Any reason why you choose to use `$.Deferred` and not ES6 Promises? – trincot Apr 06 '17 at 22:29

1 Answers1

2

You could promisify the geocoder method, so that it does not get a callback as argument, but returns a promise. Then you could create an array of promises, each created by this new function. Finally, you could use $.when to wait for all these promises to resolve, concatenate the results and return that as a promised value of the overall geocodeByLocationIdByArray method.

This is untested code, but you'll get the idea:

self.geocodeByLocationIdByArray = function (locationIds) {
    // Promisify geocoder:
    function geocoderPromise(geocodingParameters) {
        var deferred = $.Deferred();
        self.geocoder.geocoder(geocodingParameters, function () {
            deferred.resolve(result);
        }, function (err) {
            deferred.reject(err);
        });
        return deferred.promise();
    }

    // Create an array of promises
    var promises = locationIds.map(function (locationId) {
        var geocodingParameters = {
            locationId: locationIds[i].locationId;
        };
        return geocoderPromise(geocodingParameters)
            .then(onGeocodeSuccess)
            .catch(function (err) { // or `fail` in jQuery < 3.0
                console.log('geocoder error occurred', err);
            });
    });
    // Wait for all promises to be resolved, and then concatenate the results
    // as the final promised value.
    return $.when.apply($, promises).then(function () {
        return [].concat.apply([], arguments); 
    });
};

Note that with this code there are no more callback arguments, but you need to treat the return value of geocodeByLocationIdByArray() as a promise too. So you would write:

self.geocodeByLocationIdByArray([....ids....]).then(function (result) {
    console.log(results);
});
trincot
  • 317,000
  • 35
  • 244
  • 286
  • thanks. idea is very good ! I just got an error with catch(function (err) { console.log('geocoder error occurred', err); }); it seems like catch is not a function – Arbejdsglæde Apr 07 '17 at 06:31
  • Ah yes, `catch` was only introduced in jQuery 3.0. You can just leave it out, or use `fail` instead. – trincot Apr 07 '17 at 06:52