Search code examples
node.jses6-promise

How to chain promise in array


I need help with ES6 Promises chaining in array processing.

How to process/define each item of array which goes into Promise.all method, when there is other async method inside resolve?

Here is simplified example:

function getData(data, callback) {
    let groupPromises = data.map(row => {
        var coordinates = getCoordinates(row);
        return Promise.resolve({
            "place": getPlaces(coordinates), //how to invoke this method
            "data": row
        };
    });     
    Promise.all(groupPromises)
        .then(groups => callback(groups))
        .catch(err => console.log(err));
    }
}

function getPlaces(coordinates) {
    return new Promise(function(resolve, reject) {
        if(coordinates == null) {
            reject();
        }
        parameters = {
            location: [coordinates.latitude, coordinates.longitude],
            rankby: "distance",
        };
        googlePlaces.searchPlace(parameters, function (error, response) {
            if (error) {
              reject(error);
            };
            resolve(response);
        });
    }
}

Solution

  • You can do it like this where you add a .then() handler to your first promise that gets the place and then when that's available returns the object you want. The resolved results of your Promise.all() will then be the array of objects you want:

    function getData(data, callback) {
        let groupPromises = data.map(row => {
            var coordinates = getCoordinates(row);
            // add .then() handler here to convert the place result
            // into the object you want it in
            return getPlaces(coordinates).then(place => {
                return {place: place, data: row};
            });
        });     
        return Promise.all(groupPromises)
            .then(groups => callback(groups))
            .catch(err => {
                console.log(err);
                throw err;
            });
        }
    }
    
    function getPlaces(coordinates) {
        return new Promise(function(resolve, reject) {
            if(coordinates == null) {
                reject();
            }
            parameters = {
                location: [coordinates.latitude, coordinates.longitude],
                rankby: "distance",
            };
            googlePlaces.searchPlace(parameters, function (error, response) {
                if (error) {
                  reject(error);
                };
                resolve(response);
            });
        }
    }
    

    FYI, since you're converting over to promises, why not just return the promise from getData() and not use a callback there at all? Your current code has no way of communicating back an error from getData() which is something that comes largely for free with promises.

    In fact with pure promises, getData() could be simplified to this:

    function getData(data, callback) {
        return Promise.all(data.map(row => {
            return getPlaces(getCoordinates(row)).then(function(place) {
                return {place: place, data: row};
            });
        }));     
    }