【问题标题】:Uncaught (in promise) TypeError: result.main is undefinedUncaught (in promise) TypeError: result.main is undefined
【发布时间】:2021-08-18 20:40:59
【问题描述】:

我正在开发一个基于天气的 API 项目以提高我的技能,但在获取数据时出现错误:

Uncaught (in promise) TypeError: result.main is undefined

这是负责从 API 获取数据的函数:

async function fetchData(cityName) {
  const API_KEY = 'MY_API_TOKEN';

  const fetchRes = {
    method: 'GET',
    redirect: 'manual',
    mode: 'cors',
  };
  const response = await fetch(
    `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${API_KEY}`,
    fetchRes
  );
  const result = await response.json();
  const data = result.main.temp;
  console.log(data);
}

使用此调用修复

fetchData("london");

我在这里使用另一个输入和搜索按钮来获取城市名称

注意:出于安全原因,我隐藏了我的 API 令牌密钥,所以这不是问题

【问题讨论】:

  • 当你console.log(result);,你看到{ main: ..., ... }了吗? (该错误是由于您尝试访问result.main.tempresult.main 未定义)
  • @ChrisG 是的,当我 console.log(result); 它记录一个包含 {main: {temp:...}} 的对象(使用 result.json() 之后)
  • console.log(result) 的确切输出是什么?
  • 1.我一直无法重现这一点。不可能得到这个输出并且仍然得到你提到的错误。 2.我唯一能够重现此错误的情况是 API 调用本身返回 401(而不是您提到的输出)
  • 这里的正确答案类似于if (result.main) { ... },即在尝试访问其属性之前检查对象是否存在)。真的没有必要在这里发布答案;这不会帮助其他任何人。这是一个非常基本的错误,特定于您在其他地方调用该函数的方式。

标签: javascript api promise fetch


【解决方案1】:

单独的效果

return 结果而不是记录它 -

async function fetchData(cityName) {
  const API_KEY = 'MY_API_TOKEN';

  const fetchRes = {
    method: 'GET',
    redirect: 'manual',
    mode: 'cors',
  };
  const response = await fetch(
    `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${API_KEY}`,
    fetchRes
  );
  const result = await response.json();
  return result.main.temp // <-- return the result
}

现在附加效果和错误处理程序 -

fetchData(...)
  .then(console.log)      // <- receives data
  .catch(console.error)   // <- receives error

您可以在单个 .then 中同时附加效果和错误处理程序 -

fetchData(...)
  .then(console.log, console.error) // <- same behaviour as above

单独关注

我建议分离关注点,以便更容易读取/写入函数 -

const getJSON = (url, opts = {}) =>
  fetch(url, opts).then(r => r.json())

现在您不必每次想要查询一些 JSON 时都重复自己 -

async function fetchData(cityName) {
  const API_KEY = 'MY_API_TOKEN';

  const url = `https://api.openweathermap.org/data/2.5/weather?q=${cityName}&appid=${API_KEY}`

  const opts = {
    method: 'GET',
    redirect: 'manual',
    mode: 'cors',
  };

  const result = await getJSON(url, opts) // <- reusable function
  return result.main.temp
}

网址处理

我建议不要使用字符串构建 URL。而是使用 URL searchParams API 以编程方式构建事物 -

async function fetchData(cityName) {
  const API_KEY = 'MY_API_TOKEN'

  // use URL api
  const u = new URL("https://api.openweathermap.org/data/2.5/weather")
  u.searchParams.set("q", cityName)
  u.searchParams.set("appid", API_KEY)

  const opts = {...}

  const result = await getJSON(u, opts) // <- pass URL object
  return result.main.temp
}

如您所见,每次需要设置/修改某些 URL 参数时都必须编写所有这些内容会很烦人。应用上面的教训,我们写href -

function href(url, params = {}) {
  const u = new URL(u)
  for (const [key, value] of Object.entries(params))
    u.searchParams.set(key, value)
  return u.toString()
}

现在您可以避免在常用函数中重复和容易出错的代码 -

async function fetchData(cityName) {
  const API_KEY = 'MY_API_TOKEN'

  // use our href helper
  const u = href("https://api.openweathermap.org/data/2.5/weather", {
    q: cityName,
    appid: API_KEY
  })

  // use getJSON helper
  const result = await getJSON(u, {...})
  return result.main.temp
}
fetchData("someCity").then(console.log, console.error)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 2015-09-18
    相关资源
    最近更新 更多