简体   繁体   中英

I can't make my Promise to properly reject with a new Error message, caught from a try/catch

I have a Promise method that parses links from the web. It returns an Object which I try to access a link key from, but when this Object is empty, it somehow skips the if I have to check its length, causing a scandalous error. Below the codes.

First, the method that is a Promise to parse the links:

* parseReporter() {
  const article = new Promise((resolve, reject) => {
    parser.parseURL(`https://www.google.com/alerts/feeds/${this.googleAlertsUrlId}/${this.reporterUrlId}`, (err, parsed) => {
      if (err) {
        reject(new Error(err))
      }

      if (parsed.feed.entries.length === 0) {
        reject(new Error('Nothing to parse'))
      }

      const link = parsed.feed.entries[0].link
      const betterLink = link.substring(42, link.indexOf('&ct='))

      mercury.parse(betterLink).then((data) => {
        resolve(data)
      }).catch((err) => {
        reject(new Error(err))
      })
    })
  })

  return article
}

And then, here's the method that calls this parseReporter() :

* _getLastestNews(userReporter) {
  const reportersOperation = new ReportersOperation()

  reportersOperation.googleAlertsUrlId = userReporter.url.split('/')[3]
  reportersOperation.reporterUrlId = userReporter.url.split('/')[4]

  try {
    return yield reportersOperation.parseReporter()
  } catch (e) {
    this.addError(HTTPResponse.STATUS_INTERNAL_SERVER_ERROR, e.message)

    return false
  }
}

The error is caused when it tries to access link from parsed.feed.entries[0] . I've already logged out the length , and I confirmed to do work and show a number, but it insists on skipping it. Am I doing something wrong with the Promise it try/catch themselves?

reject doesn't "stop" or "return" from a function like return

Therefore, your code is checking for error conditions, but continuing on, as if the data is OK

By adding return before the call to reject , you'll stop this from happening

Just the area of code with changes shown:

      // snip
      if (err) {
        return reject(new Error(err))
      }

      if (parsed.feed.entries.length === 0) {
        return reject(new Error('Nothing to parse'))
      }

      const link = parsed.feed.entries[0].link
      const betterLink = link.substring(42, link.indexOf('&ct='))
      //snip

Besides, what Jaramonda suggested, you're also using an anti-pattern when you have a promise and you do resolve and reject in both paths. You can do that much more efficiently:

  resolve(mercury.parse(betterLink));

But, what you really should do is you should promisify parser.parseURL() so you can write all the control flow logic using promises. This is much more foolproof and creates a reusable interface that uses promises that you can use elsewhere:

// make promisified version of parser.parseURL()
parser.parseURLP = function (url) {
    return new Promise((resolve, reject) => {
        parser.parseURL(url, (err, parsed) => {
            if (err) return reject(new Error(err));
            resolve(parsed);
        });
    });
};

function parseReporter() {
    return parser.parseURL(`https://www.google.com/alerts/feeds/${this.googleAlertsUrlId}/${this.reporterUrlId}`).then(parsed => {
        if (parsed.feed.entries.length === 0) {
            throw new Error('Nothing to parse');
        }

        const link = parsed.feed.entries[0].link
        const betterLink = link.substring(42, link.indexOf('&ct='))

        return mercury.parse(betterLink).catch(err => {
            // wrap error in Error object
            throw new Error(err);
        })
    })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM