Promise Chaining 和 .then/.catch 语句

Promise Chaining and .then/.catch statements

以下代码取自https://javascript.info/promise-api的最后一个任务。

当我 运行 以下内容时,我无法获得与注释指示的警报相匹配的输出。我假设我在 catch 语句中遗漏了一些东西,但我不明白我哪里出错了。感谢您的帮助!

// the whole promise chain fails with an error here
// change that:
// make errors appear as members of the results array

let urls = [
  'https://api.github.com/users/iliakan',
  // this URL is HTML page, it's invalid JSON, so response.json() fails
  '/',
  // this URL is invalid, so fetch fails
  'http://no-such-url'
];

// Fix it:
Promise.all(urls.map(url => fetch(url).catch(err=>err)))
  .then(responses => Promise.all(
    responses.map(r => r.json().catch(err=>err))
  ))
  // Demo output (no need to change):
  .then(results => {
    alert(results[0].name); // Ilya Kantor
    alert(results[1]); // SyntaxError: Unexpected token < in JSON at position 0
    alert(results[2]); // TypeError: failed to fetch (text may vary)
  });

这不起作用的原因是因为在第一个 .catch(err=>err) 语句中,它将错误视为标准(成功)结果。然后,来自 fetch 的任何错误数据都会被调用到下一个 Promise.all 语句中,因为它被视为一个好的结果,因此 r.json() 将不知道如何处理任何错误数据(来自提取('/')。

您的代码确实出错了。例如,在 Firefox 中,它会在开发人员控制台中显示 TypeError: r.json is not a function。 (我看到您正在使用 alert(),所以您可能不熟悉开发人员控制台和浏览器中可用的 console.log()。如果是这样,我建议您查看它们作为它们提供的信息可能是无价的。)

问题在于,在r.json()中,r要么是一个响应对象,要么是一个异常对象,因为先是.catch(err=>err)。由于异常对象没有 json 属性,它会抛出自己的异常。该异常未被捕获,因为它没有 try/catch 并且 .catch() 仅可用于承诺。

您可以这样做来检查并传递初始异常:

responses.map(r => r.json ? r.json().catch(err=>err) : r)