Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node js - send response after all promises are resolved

I have a route defined in NodeJS Express.

The route calls a function multiple times (which returns a promise). Value returned from these Promises are added to an Array which is then send back to the client using res.json().

The problem that I am facing is that while Promises are getting resolved, res.json() executes as it does not wait for the Promises to return. I think some kind of chaining mechanism would be needed but can't make out how to do it.

Below is my code

app.get('/markers', function(req, res) {
       var markers = [];
    var marker1 = {"id": 1, "name": "London"};
 // Get the lat and lng based on the address
    geocoding(marker1.name).then(function(geocode) {
        marker1.lat = geocode[0].latitude;
        marker1.lng = geocode[0].longitude;
        markers.push(marker1);
    }, function(error) {
        console.log(error);
    })

    var marker2 = {"id": 2, "name": "Chicago" };
    geocoding(marker2.name).then(function(geocode) {
        marker2.lat = geocode[0].latitude;
        marker2.lng = geocode[0].longitude;
        markers.push(marker2);
    }, function(error) {
        console.log(error);
    })
     var marker3 = {"id": 3, "name": "Munich" };
     geocoding(marker3.name).then(function(geocode) {
        marker3.lat = geocode[0].latitude;
        marker3.lng = geocode[0].longitude;
        markers.push(marker3);
    }, function(error) {
        console.log(error);
    })
  // return the lat and lng array to the client
    res.json(markers);

})

How can I ensure that ' res.json(markers);' is executed after all the three Promises are resolved.

like image 332
kayasa Avatar asked Jan 06 '23 15:01

kayasa


2 Answers

You just use Promise.all, which will resolve when all promises are resolved:

app.get('/markers', function(req, res) {
    var markers = [];
    var marker1 = {"id": 1, "name": "London"};

 // Get the lat and lng based on the address
    var prom1 = geocoding(marker1.name).then(function(geocode) {
        marker1.lat = geocode[0].latitude;
        marker1.lng = geocode[0].longitude;
        markers.push(marker1);
    }, function(error) {
        console.log(error);
    })

    var marker2 = {"id": 2, "name": "Chicago" };
    var prom2 = geocoding(marker2.name).then(function(geocode) {
        marker2.lat = geocode[0].latitude;
        marker2.lng = geocode[0].longitude;
        markers.push(marker2);
    }, function(error) {
        console.log(error);
    });

    var marker3 = {"id": 3, "name": "Munich" };
    var prom3 = geocoding(marker3.name).then(function(geocode) {
        marker3.lat = geocode[0].latitude;
        marker3.lng = geocode[0].longitude;
        markers.push(marker3);
    }, function(error) {
        console.log(error);
    });
  // return the lat and lng array to the client

    Promise.all([prom1, prom2, prom3]).then(function() {res.json(markers);}).catch(function(err) {console.error(err);});
})
like image 104
Vsevolod Goloviznin Avatar answered Jan 14 '23 11:01

Vsevolod Goloviznin


You could await for multiple promises results using Promise.all function.

You could also use Array.prototype.map to prepare an array of promises to reduce code duplication.

And you should properly handle promises rejections.

app.get('/markers', function(req, res, next) {
  var markers = [{
    id: 1,
    name: 'London'
  }, {
    id: 2,
    name: 'Chicago'
  }, {
    id: 3,
    name: 'Munich'
  }];
  // you could use .map to generate an array of promises
  var promises = markers.map(function (marker) {
    return geocoding(marker.name);
  })
  // and then use Promise.all to await their results
  Promise.all(promises).then(function (geocodes) {
    // you could use .map again to generate resulting json
      res.json(geocodes.map(function (geocode) {
      return {
        lat: geocode[0].latitude,
        lng: geocode[0].longitude
      }
    }));
  }).catch(next) // handle promise rejection
})
like image 40
Leonid Beschastny Avatar answered Jan 14 '23 12:01

Leonid Beschastny