【问题标题】:Promise Chaining error handling承诺链错误处理
【发布时间】:2017-10-30 12:35:28
【问题描述】:

我正在学习如何在没有库的情况下使用 Promise。根据我的阅读,我可以将 Promise 链接在一起,然后在最后添加 .catch 以进行错误处理。

我期待什么

因此,如果我将 URL 更改为一些错误的 url,我不应该发现错误并停止整个程序继续运行吗?

我现在看到了什么?

当我输入一个错误的 url 时,程序只会抛出一个错误,而不是像拒绝一样处理它。

const request = require("request");

new Promise((resolve, reject) => {
  request(
    "http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
    (err, res, body) => {
      if (err) {
        reject("bad call on geo code!");
      }
      resolve(JSON.parse(body).results[0].geometry.location);
    }
  );
})
  .then(res => {
    const {lat, lng} = res;
    return new Promise((resolve, reject) => {
      request(
        `https://api.darksky.net/forecast/6fb416a8313aabd902a22558e07cc032/${lat},${lng}`,
        (err, res, body) => {
          if (err) {
            reject("bad call on darksky");
          }
          resolve(JSON.parse(body));
        }
      );
    });
  })
  .then(res => {
    const currentTemp = res.currently.temperature;
    const feelTemp = res.currently.apparentTemperature;
    const temps = {currentTemp, feelTemp};
    return new Promise((resolve, reject) => {
      request(
        "http://ron-swanson-quotes.herokuapp.com/v2/quotes",
        (err, res, body) => {
          if (err) {
            reject("bad call on quotes");
          }
          resolve({temps, body});
        }
      );
    });
  })
  .then(res => {
    console.log(
      `Today's weather is ${res.temps.currentTemp}, and it feels like ${res
        .temps
        .feelTemp}! \nAnd here is your stupid quote of the day: \n${JSON.parse(
        res.body
      )[0]}`
    );
  })
  .catch(err => {
    console.log(err);
  });

错误信息:

这并没有真正的意义,基本上错误并没有停止程序,它只是传递给下一个promise。该承诺收到错误但无法解析它,因为它不是预期的 JSON 格式。

SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at Promise.then.then.then.res (/Users/leoqiu/reacto/playground/6_promiseMethod.js:48:74)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)

【问题讨论】:

  • 错误是什么?
  • 这取决于我在哪个阶段更改 url,所以基本上拒绝抛出错误,并且该错误消息被传递下来,由 res 处理,用于下一个 Promise。所以错误只是JSON解析错误。
  • 还在中添加了错误
  • 不,你只需要在你的reject() 调用之后做一个return。另请注意,您的 catch() 回调正在工作,因为它正在打印捕获的错误消息,它只是打印出您没有预料到的错误。
  • 仅供参考,让 Promise 的编码更易于使用。您有 3 次对 request 的调用,您已单独“承诺”,这很好,因为它们都对结果做了略微不同的事情。但是,您可以通过创建一个“承诺的”request 函数来简化这个过程……看看您的代码可以变得多么简单in this fiddle

标签: javascript node.js promise


【解决方案1】:

当您在if 语句中调用reject() 时,您不会返回,也不会使用else,因此您的resolve(JSON.parse(body).results[0].geometry.location); 仍会被执行并引发异常。

你可以改成这样:

new Promise((resolve, reject) => {
  request(
    "http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
    (err, res, body) => {
      if (err) {
        reject("bad call on geo code!");
        return;
      }
      resolve(JSON.parse(body).results[0].geometry.location);
    }
  );
})

人们认为reject()break 或其他一些控制流语句一样工作是一个常见的错误,因为reject() 是一种承诺控制流。但是,它不会在您的块中停止执行,因此您需要在它之后使用 return 或使用 else

或者,我更喜欢使用if/else,因为我认为它使逻辑更加明显:

new Promise((resolve, reject) => {
  request(
    "http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
    (err, res, body) => {
      if (err) {
        reject("bad call on geo code!");
      } else {
        resolve(JSON.parse(body).results[0].geometry.location);
      }
    }
  );
})

【讨论】:

    【解决方案2】:

    基于 Patrick Evans 的建议...

    reject 不会阻止程序运行,因此错误消息会传递到下一个 Promise,这就是抛出 json 解析错误的原因。

    解决方法就是在拒绝中加入return

    if (err) {
        reject("bad call on geo code!");
        return err;
      }
    

    【讨论】:

      猜你喜欢
      • 2015-07-03
      • 1970-01-01
      • 2014-08-12
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 2018-06-01
      • 2018-09-18
      • 1970-01-01
      相关资源
      最近更新 更多