kittu
kittu

Reputation: 7018

unable to resolve inner promise in javascript

Unable to resolve or come out of inner promise so I can send the data back to client side.

Code:

function getAmazonData(url, isRatings) {
    var parsedData;
    var ItemLookup;
    var ratingsURL;

    return new Promise(function (resolve, reject) {

        request(url, function (err, response, body) {
            if (err) return reject(err);
            parseXML(body, function (err, parsedData) {
                if (err) return reject(err);
                ItemLookup = parsedData['ItemLookupResponse'];

                if (ItemLookup && ItemLookup.Items && ItemLookup.Items.length > 0) {
                    // Request Error
                    if (ItemLookup.Items[0].Request && ItemLookup.Items[0].Request.length > 0 && ItemLookup.Items[0].Request[0].Errors) {
                        return reject(ItemLookup.Items[0].Request[0].Errors);
                    } else if (ItemLookup.Items[0].Item) {
                        ratingsURL = ItemLookup.Items[0].Item[0].CustomerReviews[0].IFrameURL[0];
                        if (isRatings) {
                            console.log('getting ratings...');
                            return new Promise(function (resolve2, reject2) {
                                request(ratingsURL, { json: true }, function (ratingsError, ratingBody) {
                                    if (ratingsError) {
                                        return reject2('Error in getting ratings');
                                    }
                                    ItemLookup.Items[0].Item[0].CustomerReviews.push({ Ratings: ratingBody });
                                    resolve2(ItemLookup.Items[0].Item[0].CustomerReviews);
                                });
                            });
                        }
                        console.log('Resolved: ', ItemLookup.Items[0].Item);
                        resolve(ItemLookup.Items[0].Item);
                    }
                }
            });
        });
    });
}

amazon_router.get('/getDetails', function (req, res, next) {
    var amazonApi = decodeURIComponent(req.query.url);
    var amzonApiUrl = amazonApi.replace(/\+/g, '%2B');
    var isRatings = decodeURIComponent(req.query.ratings);
    console.log('');
    console.log('amazon api url ', amzonApiUrl);
    console.log('');

    getAmazonData(amzonApiUrl, isRatings).then(function (err, response) {
        if (err) res.send(err);
        res.send(response);
    });
});

The data is never sent after resolving promise here at LINE 10: res.send(response); There's something wrong with inner promise but I am not sure not do I fix it?

Upvotes: 0

Views: 77

Answers (2)

m1ch4ls
m1ch4ls

Reputation: 3435

It looks like you are mixing callbacks and Promises. I would recommend wrapping all calls to Promises.

From the looks of it you don't need inner Promise because request expects a callback so you can easily resolve the outer one.

You also have some branches of if statements that don't call resolve or reject (marked in the code bellow with comments). You have to call resolve/reject in all branches otherwise the Promise 'might do nothing' in case it hits the branch.

function getAmazonData(url, isRatings) {
  var parsedData;
  var ItemLookup;
  var ratingsURL;

  return new Promise(function (resolve, reject) {
    request(url, function (err, response, body) {
      if (err) return reject(err);
      parseXML(body, function (err, parsedData) {
        if (err) return reject(err);
        ItemLookup = parsedData['ItemLookupResponse'];

        if (ItemLookup && ItemLookup.Items && ItemLookup.Items.length > 0) {
          // Request Error
          if (ItemLookup.Items[0].Request && ItemLookup.Items[0].Request.length > 0 && ItemLookup.Items[0].Request[0].Errors) {
            reject(ItemLookup.Items[0].Request[0].Errors);
          } else if (ItemLookup.Items[0].Item) {
            ratingsURL = ItemLookup.Items[0].Item[0].CustomerReviews[0].IFrameURL[0];
            if (isRatings) {
              console.log('getting ratings...');
              request(ratingsURL, { json: true }, function (ratingsError, ratingBody) {
                if (ratingsError) {
                  reject(new Error('Error in getting ratings'));
                  return;
                }
                ItemLookup.Items[0].Item[0].CustomerReviews.push({ Ratings: ratingBody });
                resolve(ItemLookup.Items[0].Item[0].CustomerReviews);
              });
            } else {
              console.log('Resolved: ', ItemLookup.Items[0].Item);
              resolve(ItemLookup.Items[0].Item);
            }
          } else {
            // resolve or reject here
          }
        } else {
          // resolve or reject here
        }
      });
    });
  });
}

Wrapping call to Promise:

function requestAsPromised(url) {
  return new Promise(function (resolve, reject) {
    request(url, function (err, response, body) {
      if (err) {
        reject(err);
      } else {
        resolve(body)
      }
    });
  })
}

Upvotes: 1

Kamalakannan J
Kamalakannan J

Reputation: 2998

You need to use return to return the inner promise(s),

function getAmazonData(url, isRatings) {
    var parsedData;
    var ItemLookup;
    var ratingsURL;

    return new Promise(function (resolve, reject) {
        return request(url, function (err, response, body) {
            if (err) return reject(err);
            return parseXML(body, function (err, parsedData) {
                if (err) return reject(err);
                ItemLookup = parsedData['ItemLookupResponse'];

                if (ItemLookup && ItemLookup.Items && ItemLookup.Items.length > 0) {
                    // Request Error
                    if (ItemLookup.Items[0].Request && ItemLookup.Items[0].Request.length > 0 && ItemLookup.Items[0].Request[0].Errors) {
                        return reject(ItemLookup.Items[0].Request[0].Errors);
                    } else if (ItemLookup.Items[0].Item) {
                        ratingsURL = ItemLookup.Items[0].Item[0].CustomerReviews[0].IFrameURL[0];
                        if (isRatings) {
                            console.log('getting ratings...');
                            return new Promise(function (resolve2, reject2) {
                                request(ratingsURL, { json: true }, function (ratingsError, ratingBody) {
                                    if (ratingsError) {
                                        return reject2('Error in getting ratings');
                                    }
                                    ItemLookup.Items[0].Item[0].CustomerReviews.push({ Ratings: ratingBody });
                                    resolve2(ItemLookup.Items[0].Item[0].CustomerReviews);
                                });
                            });
                        }
                        console.log('Resolved: ', ItemLookup.Items[0].Item);
                        return resolve(ItemLookup.Items[0].Item);
                    }
                }
            });
        });
    });
}

Since it looks like Node.js code, try using async/await

Upvotes: 0

Related Questions