Search code examples
javascriptnode.jses6-promise

Figuring the complexity of Promise.all


I have been struggling for quite some time to get this multiple async nodejs request apis to work but unfortunately i am not able to get them work.

Index.js Code:

service.get(
  "/restraunts",
  versionRoutes({
    "1.0.0": getRestrauntsList
  })
);

function getRestrauntsList(req, res, next) {
  console.log("Started getRestrauntsList");
  file1
    .appEnvironment(req, res, next)
    .then(function(result) {
      return file2.getRestrauntsList(req, res, next);
    })
    .then(function(result) {
      res.status(200).send(result);
      return;
    })
    .catch(function(errorResult) {
      res.status(500).send(errorResult);
      return;
    });
}

File2.js

module.exports = {
  getRestrauntsList: function(req, res, next) {
    console.log("getRestrauntsList started..");
    var cities = [1, 2, 3, 4, 5];
    let restrauntsList = [];
    let urlArray = [];
    var restrauntsListPromise = cities.map(function(id) {
      return new Promise(function(resolve, reject) {
        var options = {
          method: "GET",
          url: "someurl/" + id + "/restaurants",
          headers: {
            "AUTH-TOKEN": "TOKEN"
          }
        };
        request(options, function(error, response, body) {
          if (error) {
            if ("message" in error) {
              errorMsg = error.message;
              var result = {
                status: "error",
                message: errorMsg
              };
            } else {
              var result = {
                status: "error",
                message: "Resource Timeout."
              };
            }
            reject(result);
            return promise;
          }
          console.log(
            "Response: " + JSON.stringify(response)
          );
          if (response.statusCode === 200 || response.statusCode === 201) {
            body = JSON.parse(body);
            if (body.success) {
              let result = {
                status: "success",
                data: body.result
              };
              resolve(result);
            } else {
              let result = {
                status: "error",
                message: body.error
              };
              reject(result);
            }
          } else {
            let result = {
              status: "error",
              message: body.error
            };
            reject(result);
          }
        });
      });
    });
    console.log('restrauntsListPromise:' + JSON.stringify(restrauntsListPromise));
    Promise.all(restrauntsListPromise).then(function(result) {
      var content = result.map(function(restraunts) {
        return restrauntsList.push(restraunts.body);
      });
      //  res.send(content);
      resolve({
        restrauntsList: restrauntsList
      });
      return promise;
    });
  },
};

Ideally i expect to get the response of all the apis in the

restrauntsListPromise

and then using Promise.all i should iterate all the promises and formulate my required object.

The response of my code however is

restrauntsListPromise:[{},{},{},{},{}]

and then

Response: {"statusCode":200,"body":"{\"success\":true,\"res

Response: {"statusCode":200,"body":"{\"success\":true,\"res

Response: {"statusCode":200,"body":"{\"success\":true,\"res

Response: {"statusCode":200,"body":"{\"success\":true,\"res

Response: {"statusCode":200,"body":"{\"success\":true,\"res

Ideally what should happen is i should be able to pass the combined result of all the five apis calls as a single object back to the calling promise here

.then(function(result) {
    res.status(200).send(result);
    return;
  })

The problem being the method getRestrauntsList finishes execution and then after some time, i get the responses of the apis.


Solution

  • You are looking for

    return Promise.all(restrauntsListPromise).then(function(result) { /*
    ^^^^^^ */
        var contents = result.map(function(restaurants) {
            return restaurants.body;
    //      ^^^^^^^^^^^^^^^^^^^^^^^^
        });
        return {restaurantsList: contents};
    //  ^^^^^^
    });
    

    You need to return the promise chain from the getRestrauntsList method, you should return the value from the map callback instead of using push on an array, and you will need to return from the then callback - there is no resolve function as you're not inside a new Promise constructor that you only need for callback APIs.