尝试针对使用 OpenWeatherMaps API 的城市的无效提取生成警报
Trying to generate alerts for invalid fetches for cities with OpenWeatherMaps API
所以我正在尝试为试图通过 OpenWeatherMaps 访问无效城市的天气数据的用户生成警报 API。
我大部分时间都在那里。然而,当我对此进行测试时,发生了两件事:
- 浏览器生成正确的警报。
但是,一旦您单击警报的确认按钮...
- “未处理的拒绝(TypeError):无法解构‘(中间值)’的 属性 'data',因为它未定义。”
这是我目前使用的代码:
const fetchWeather = async (query) => {
const { data } = await axios.get(
URL,
{
params: {
q: query,
units: "metric",
APPID: API_KEY,
},
}).catch (function (error) {
alert(error.response.data.message)
})
};
完整代码:
Search.jsx 分量:
import React, { useState } from "react";
import fetchWeather from "../api/fetchWeather";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import InputAdornment from '@material-ui/core/InputAdornment';
import SearchIcon from '@material-ui/icons/Search';
const Search = () => {
let [displayResults, setDisplayResults] = useState(false);
let [query, setQuery] = useState("");
let [feelsLike, setFeelsLike] = useState(0);
let [mainTemp, setMainTemp] = useState(0);
let [description, setDescription] = useState("");
let [main, setMain] = useState("");
let [iconID, setIconID] = useState("");
let [windSpeed, setWindSpeed] = useState("");
let [windGust, setWindGust] = useState("");
let [windDirection, setWindDirection] = useState("");
let [name, setName] = useState("");
let [country, setCountry] = useState("");
const useStyles = makeStyles((theme) => ({
button: {
backgroundColor: "#FDB124",
color: "black",
fontFamily: "Mortal Kombat",
"&:hover": {
background: "#B57602",
},
},
root: {
"& > *": {
display: 'flex',
margin: theme.spacing(1),
// width: "25ch",
},
input: {
color: "white",
},
primary: {
backgroundColor: "#FDB124",
},
"& label.Mui-focused": {
color: "#FDB124",
},
"& label": {
color: "#FDB124",
fontFamily: "Mortal Kombat",
},
"& input": {
color: "#FDB124",
fontFamily: "Mortal Kombat",
},
"& .MuiInput-underline:after": {
borderBottomColor: "#FDB124",
},
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#FDB124",
},
"&:hover fieldset": {
borderColor: "#FDB124",
},
"&.Mui-focused fieldset": {
borderColor: "#FDB124",
},
},
},
}));
const weatherSearch = async (e) => {
if (e.key === "Enter") {
const data = await fetchWeather(query);
setDisplayResults(true);
setFeelsLike(data.main.feels_like);
setMainTemp(data.main.temp);
setDescription(data.weather[0].description);
setMain(data.weather[0].main);
setIconID(data.weather[0].icon);
setWindSpeed(data.wind.speed);
setWindGust(data.wind.gust);
setWindDirection(data.wind.deg);
setName(data.name);
setCountry(data.sys.country);
setQuery("");
}
};
const classes = useStyles();
return (
<div>
<h1 className="cityChoose">CHOOSE YOUR CITY:</h1>
<TextField
id="outlined-basic"
label="Enter City"
variant="outlined"
color="secondary"
size="small"
spellCheck="false"
className={classes.root}
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyPress={weatherSearch}
InputProps={{
startAdornment: (
<InputAdornment position="start" style={{color: "#FDB124"}}>
<SearchIcon />
</InputAdornment>
),
}}
/>
{displayResults ? null : <h4>Example: Chicago, IL, US</h4>}
{displayResults ? (
<>
<h1>The current weather in {name}, {country} is:</h1>
<span>
<div>
{description}
<br />
<img
src={"http://openweathermap.org/img/wn/" + iconID + "@2x.png"}
/>
</div>
<h2>Temperature:</h2>
<br />
<div>
{(mainTemp * 1.8 + 32).toFixed(1)} °F / {mainTemp.toFixed(1)}{" "}
°C
</div>
<br />
<br />
<h2>Winds:</h2>
<div>Wind Direction: {windDirection}</div>
<div>Wind Speed: {windSpeed} MPH</div>
<div>Wind Gusts: {windGust} MPH</div>
</span>
</>
) : null}
</div>
);
};
export default Search;
fetchWeather.jsx:
import React from "react";
import axios from "axios";
const URL = "https://api.openweathermap.org/data/2.5/weather";
const API_KEY = "*key is here*";
const fetchWeather = async (query) => {
const { data } = await axios.get(
URL,
{
params: {
q: query,
units: "metric",
APPID: API_KEY,
},
}).catch (function (error) {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log("Error: ", error.message);
}
});
console.log(data);
return data;
};
export default fetchWeather;
尝试像这样检查错误:
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log("Error", error.message);
}
工作样本:https://codesandbox.io/s/openweathermap-test-forked-35781?file=/src/index.js:434-749
好的,所以您遇到的问题与 axios 抛出错误并且不会 return 具有键 data
的对象返回 const { data } = await axios.get(
这一事实有关。解决这个问题非常简单。
它无法从你错误的 axios 调用中解构 data
的原因是你没有在 catch 块中容纳它
.catch (function (error) {
alert(error.response.data.message)
})
您的 catch 块应该如下所示:
.catch (error => {
return {data: error.response.data ? error.response.data : 'No data'}
}
)
所以您的 fetchWeather
函数的最终(和工作)版本是...
const fetchWeather = async (query) => {
const { data } = await axios.get(
'https://httpstat.us/400',
{
params: {
q: query,
units: "metric",
APPID: 'XXXXXXXX',
},
})
.catch (error => {
return {data: error.response.data ? error.response.data : 'No data'}
}
)
console.log(data)
};
您可以尝试使用这两个测试网址:
https://httpstat.us/200 returns 200 OK
https://httpstat.us/400 returns 400 Bad Request
后者会触发catch
。
请记住,如果您调用的域未解析为 ip(例如 http://hskjfhshgsg.com/api/sss/sss 或类似内容),我编写的代码将抛出错误.)
所以我正在尝试为试图通过 OpenWeatherMaps 访问无效城市的天气数据的用户生成警报 API。
我大部分时间都在那里。然而,当我对此进行测试时,发生了两件事:
- 浏览器生成正确的警报。
但是,一旦您单击警报的确认按钮...
- “未处理的拒绝(TypeError):无法解构‘(中间值)’的 属性 'data',因为它未定义。”
这是我目前使用的代码:
const fetchWeather = async (query) => {
const { data } = await axios.get(
URL,
{
params: {
q: query,
units: "metric",
APPID: API_KEY,
},
}).catch (function (error) {
alert(error.response.data.message)
})
};
完整代码:
Search.jsx 分量:
import React, { useState } from "react";
import fetchWeather from "../api/fetchWeather";
import { makeStyles } from "@material-ui/core/styles";
import TextField from "@material-ui/core/TextField";
import InputAdornment from '@material-ui/core/InputAdornment';
import SearchIcon from '@material-ui/icons/Search';
const Search = () => {
let [displayResults, setDisplayResults] = useState(false);
let [query, setQuery] = useState("");
let [feelsLike, setFeelsLike] = useState(0);
let [mainTemp, setMainTemp] = useState(0);
let [description, setDescription] = useState("");
let [main, setMain] = useState("");
let [iconID, setIconID] = useState("");
let [windSpeed, setWindSpeed] = useState("");
let [windGust, setWindGust] = useState("");
let [windDirection, setWindDirection] = useState("");
let [name, setName] = useState("");
let [country, setCountry] = useState("");
const useStyles = makeStyles((theme) => ({
button: {
backgroundColor: "#FDB124",
color: "black",
fontFamily: "Mortal Kombat",
"&:hover": {
background: "#B57602",
},
},
root: {
"& > *": {
display: 'flex',
margin: theme.spacing(1),
// width: "25ch",
},
input: {
color: "white",
},
primary: {
backgroundColor: "#FDB124",
},
"& label.Mui-focused": {
color: "#FDB124",
},
"& label": {
color: "#FDB124",
fontFamily: "Mortal Kombat",
},
"& input": {
color: "#FDB124",
fontFamily: "Mortal Kombat",
},
"& .MuiInput-underline:after": {
borderBottomColor: "#FDB124",
},
"& .MuiOutlinedInput-root": {
"& fieldset": {
borderColor: "#FDB124",
},
"&:hover fieldset": {
borderColor: "#FDB124",
},
"&.Mui-focused fieldset": {
borderColor: "#FDB124",
},
},
},
}));
const weatherSearch = async (e) => {
if (e.key === "Enter") {
const data = await fetchWeather(query);
setDisplayResults(true);
setFeelsLike(data.main.feels_like);
setMainTemp(data.main.temp);
setDescription(data.weather[0].description);
setMain(data.weather[0].main);
setIconID(data.weather[0].icon);
setWindSpeed(data.wind.speed);
setWindGust(data.wind.gust);
setWindDirection(data.wind.deg);
setName(data.name);
setCountry(data.sys.country);
setQuery("");
}
};
const classes = useStyles();
return (
<div>
<h1 className="cityChoose">CHOOSE YOUR CITY:</h1>
<TextField
id="outlined-basic"
label="Enter City"
variant="outlined"
color="secondary"
size="small"
spellCheck="false"
className={classes.root}
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyPress={weatherSearch}
InputProps={{
startAdornment: (
<InputAdornment position="start" style={{color: "#FDB124"}}>
<SearchIcon />
</InputAdornment>
),
}}
/>
{displayResults ? null : <h4>Example: Chicago, IL, US</h4>}
{displayResults ? (
<>
<h1>The current weather in {name}, {country} is:</h1>
<span>
<div>
{description}
<br />
<img
src={"http://openweathermap.org/img/wn/" + iconID + "@2x.png"}
/>
</div>
<h2>Temperature:</h2>
<br />
<div>
{(mainTemp * 1.8 + 32).toFixed(1)} °F / {mainTemp.toFixed(1)}{" "}
°C
</div>
<br />
<br />
<h2>Winds:</h2>
<div>Wind Direction: {windDirection}</div>
<div>Wind Speed: {windSpeed} MPH</div>
<div>Wind Gusts: {windGust} MPH</div>
</span>
</>
) : null}
</div>
);
};
export default Search;
fetchWeather.jsx:
import React from "react";
import axios from "axios";
const URL = "https://api.openweathermap.org/data/2.5/weather";
const API_KEY = "*key is here*";
const fetchWeather = async (query) => {
const { data } = await axios.get(
URL,
{
params: {
q: query,
units: "metric",
APPID: API_KEY,
},
}).catch (function (error) {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log("Error: ", error.message);
}
});
console.log(data);
return data;
};
export default fetchWeather;
尝试像这样检查错误:
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log("Error", error.message);
}
工作样本:https://codesandbox.io/s/openweathermap-test-forked-35781?file=/src/index.js:434-749
好的,所以您遇到的问题与 axios 抛出错误并且不会 return 具有键 data
的对象返回 const { data } = await axios.get(
这一事实有关。解决这个问题非常简单。
它无法从你错误的 axios 调用中解构 data
的原因是你没有在 catch 块中容纳它
.catch (function (error) {
alert(error.response.data.message)
})
您的 catch 块应该如下所示:
.catch (error => {
return {data: error.response.data ? error.response.data : 'No data'}
}
)
所以您的 fetchWeather
函数的最终(和工作)版本是...
const fetchWeather = async (query) => {
const { data } = await axios.get(
'https://httpstat.us/400',
{
params: {
q: query,
units: "metric",
APPID: 'XXXXXXXX',
},
})
.catch (error => {
return {data: error.response.data ? error.response.data : 'No data'}
}
)
console.log(data)
};
您可以尝试使用这两个测试网址:
https://httpstat.us/200 returns 200 OK
https://httpstat.us/400 returns 400 Bad Request
后者会触发catch
。
请记住,如果您调用的域未解析为 ip(例如 http://hskjfhshgsg.com/api/sss/sss 或类似内容),我编写的代码将抛出错误.)