重构来自 API 调用的重复 if 语句
Refactoring repetitive if statements from API call
我使用了四个非常相似的 if 语句来为我的天气应用程序项目选择要显示的天气图标。
我尝试过使用 for 循环、forEach、谷歌搜索、试验,但我似乎无法完全重构它并保留其功能。
我从OpenWeatherMap中取出了天气预报数组的前四项,并根据特定数组的天气代码(代表时间)显示相应的图标。
我有这个功能,但是我有很多重复的代码,有人可以帮我重构这个或者给我指明正确的方向吗?这是我的第一个正式项目,所以请保持温柔!提前感谢您的帮助:)
const getForecast = async (api) => {
try {
const res = await axios.get(api);
console.log(res);
const weather1 = res.data.list[0].weather[0].main;
const time1 = res.data.list[0].dt_txt.substr(11, 15);
const weather2 = res.data.list[1].weather[0].main;
const time2 = res.data.list[1].dt_txt.substr(11, 15);
const weather3 = res.data.list[2].weather[0].main;
const time3 = res.data.list[2].dt_txt.substr(11, 15);
const weather4 = res.data.list[3].weather[0].main;
const time4 = res.data.list[3].dt_txt.substr(11, 15);
forecastTime1.textContent = time1;
forecastTime2.textContent = time2;
forecastTime3.textContent = time3;
forecastTime4.textContent = time4;
if (weather1 === "Thunderstorm") {
forecastDisplay1.src = `img/thunder.svg`;
} else if (weather1 === "Drizzle") {
forecastDisplay1.src = `img/drizzle.svg`;
} else if (weather1 === "Rain") {
forecastDisplay1.src = `img/rain.svg`;
} else if (weather1 === "Snow") {
forecastDisplay1.src = `img/snowy.svg`;
} else if (
weather1 === "Mist" ||
weather1 === "Smoke" ||
weather1 === "Haze" ||
weather1 === "Dust" ||
weather1 === "Fog" ||
weather1 === "Sand" ||
weather1 === "Ash" ||
weather1 === "Squall" ||
weather1 === "Tornado"
) {
forecastDisplay1.src = `img/cloudy.svg`;
} else if (weather1 === "Clear") {
forecastDisplay1.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather1 === "Clouds") {
forecastDisplay1.src = `img/cloudy.svg`;
}
if (weather2 === "Thunderstorm") {
forecastDisplay2.src = `img/thunder.svg`;
} else if (weather2 === "Drizzle") {
forecastDisplay.src = `img/drizzle.svg`;
} else if (weather2 === "Rain") {
forecastDisplay2.src = `img/rain.svg`;
} else if (weather2 === "Snow") {
forecastDisplay2.src = `img/snowy.svg`;
} else if (
weather2 === "Mist" ||
weather2 === "Smoke" ||
weather2 === "Haze" ||
weather2 === "Dust" ||
weather2 === "Fog" ||
weather2 === "Sand" ||
weather2 === "Ash" ||
weather2 === "Squall" ||
weather2 === "Tornado"
) {
forecastDisplay2.src = `img/cloudy.svg`;
} else if (weather2 === "Clear") {
forecastDisplay2.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather2 === "Clouds") {
forecastDisplay2.src = `img/cloudy.svg`;
}
if (weather3 === "Thunderstorm") {
forecastDisplay3.src = `img/thunder.svg`;
} else if (weather3 === "Drizzle") {
forecastDisplay3.src = `img/drizzle.svg`;
} else if (weather3 === "Rain") {
forecastDisplay3.src = `img/rain.svg`;
} else if (weather3 === "Snow") {
forecastDisplay3.src = `img/snowy.svg`;
} else if (
weather3 === "Mist" ||
weather3 === "Smoke" ||
weather3 === "Haze" ||
weather3 === "Dust" ||
weather3 === "Fog" ||
weather3 === "Sand" ||
weather3 === "Ash" ||
weather3 === "Squall" ||
weather3 === "Tornado"
) {
forecastDisplay3.src = `img/cloudy.svg`;
} else if (weather3 === "Clear") {
forecastDisplay3.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather3 === "Clouds") {
forecastDisplay3.src = `img/cloudy.svg`;
}
if (weather4 === "Thunderstorm") {
forecastDisplay4.src = `img/thunder.svg`;
} else if (weather4 === "Drizzle") {
forecastDisplay4.src = `img/drizzle.svg`;
} else if (weather4 === "Rain") {
forecastDisplay4.src = `img/rain.svg`;
} else if (weather4 === "Snow") {
forecastDisplay4.src = `img/snowy.svg`;
} else if (
weather4 === "Mist" ||
weather4 === "Smoke" ||
weather4 === "Haze" ||
weather4 === "Dust" ||
weather4 === "Fog" ||
weather4 === "Sand" ||
weather4 === "Ash" ||
weather4 === "Squall" ||
weather4 === "Tornado"
) {
forecastDisplay4.src = `img/cloudy.svg`;
} else if (weather4 === "Clear") {
forecastDisplay4.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather4 === "Clouds") {
forecastDisplay4.src = `img/cloudy.svg`;
}
} catch (e) {
console.log(e);
}
};
为什么不使用 switch 语句而不是 if/else statements.Its 更简单,更少 code.https://www.w3schools.com/js/js_switch.asp
我可能会做类似下面的事情。永远不要使用具有相同名称的变量,只是一个数字来区分它们,而是使用数组或类似数组的结构,这样你就可以遍历它们:
// This is not defined in the snippet you showed us, but it makes it easier to loop
const forecastTime = document.querySelectorAll('.forecast-time'),
forecastDisplay = document.querySelectorAll('.forecast-display');
const res = await axios.get(api);
res.data.list.slice(0, 4) // If there are more than 4, keep the first 4?
.forEach(({ weather, dt_txt }, i) => {
forecastTime[i].textContent = dt_txt.substr(11, 15);
forecastDisplay[i].src = getImageForWeatherType(weather[0].main);
});
function getImageForWeatherType(type) {
if (type === "Clear") { return `img/clear-${getDayOrNight()}.svg`; } // Special case
const imageMap = {
`img/thunder.svg`: ['Thunderstorm'],
`img/drizzle.svg`: ['Drizzle'],
`img/rain.svg`: ['Rain'],
`img/snowy.svg`: ['Snow'],
`img/cloudy.svg`: ["Mist", "Smoke", "Haze", "Dust", "Fog", "Sand",
"Ash", "Squall", "Tornado", "Clouds"]
};
return Object.keys(imageMap).find(key => imageMap[key].includes(type));
}
你可以使用这个模式:
const getForecast = async (api) => {
const map_weather_img = {
'Thunderstorm': 'img/thunder.svg',
'Drizzle': 'img/drizzle.svg',
'Rain': 'img/rain.svg',
'Snow': 'img/snowy.svg',
'Mist': 'img/cloudy.svg',
'Smoke': 'img/cloudy.svg',
'Haze': 'img/cloudy.svg',
'Dust': 'img/cloudy.svg',
'Fog': 'img/cloudy.svg',
'Sand': 'img/cloudy.svg',
'Ash': 'img/cloudy.svg',
'Squall': 'img/cloudy.svg',
'Tornado': 'img/cloudy.svg',
'Clear': `img/clear-${getDayOrNight()}.svg`,
'Clouds': 'img/cloudy.svg',
};
try {
const res = await axios.get(api);
console.log(res);
const weather1 = res.data.list[0].weather[0].main;
const time1 = res.data.list[0].dt_txt.substr(11, 15);
const weather2 = res.data.list[1].weather[0].main;
const time2 = res.data.list[1].dt_txt.substr(11, 15);
const weather3 = res.data.list[2].weather[0].main;
const time3 = res.data.list[2].dt_txt.substr(11, 15);
const weather4 = res.data.list[3].weather[0].main;
const time4 = res.data.list[3].dt_txt.substr(11, 15);
forecastTime1.textContent = time1;
forecastTime2.textContent = time2;
forecastTime3.textContent = time3;
forecastTime4.textContent = time4;
forecastDisplay1.src = map_weather_img[weather1];
forecastDisplay2.src = map_weather_img[weather2];
forecastDisplay3.src = map_weather_img[weather3];
forecastDisplay4.src = map_weather_img[weather4];
} catch (e) {
console.log(e);
}
};
但为了更灵活,您可以使用这个:
// array of HTML Element
const forecast = [
{
display: /*HTML element*/,
time: /*HTML element*/,
},
{
display: /*HTML element*/,
time: /*HTML element*/,
},
...
];
const getForecast = async (api) => {
const table = {
'Thunderstorm': 'img/thunder.svg',
'Drizzle': 'img/drizzle.svg',
'Rain': 'img/rain.svg',
'Snow': 'img/snowy.svg',
'Mist': 'img/cloudy.svg',
'Smoke': 'img/cloudy.svg',
'Haze': 'img/cloudy.svg',
'Dust': 'img/cloudy.svg',
'Fog': 'img/cloudy.svg',
'Sand': 'img/cloudy.svg',
'Ash': 'img/cloudy.svg',
'Squall': 'img/cloudy.svg',
'Tornado': 'img/cloudy.svg',
'Clear': `img/clear-${getDayOrNight()}.svg`,
'Clouds': 'img/cloudy.svg',
};
try {
const res = await axios.get(api);
console.log(res);
forecast.forEach( (f,i) => {
const weather = res.data.list[i].weather[0].main;
const time = res.data.list[i].dt_txt.substr(11, 15);
f.time.textContent = time;
f.display.src = table[weather];
});
} catch (e) {
console.log(e);
}
};
我使用了四个非常相似的 if 语句来为我的天气应用程序项目选择要显示的天气图标。
我尝试过使用 for 循环、forEach、谷歌搜索、试验,但我似乎无法完全重构它并保留其功能。
我从OpenWeatherMap中取出了天气预报数组的前四项,并根据特定数组的天气代码(代表时间)显示相应的图标。
我有这个功能,但是我有很多重复的代码,有人可以帮我重构这个或者给我指明正确的方向吗?这是我的第一个正式项目,所以请保持温柔!提前感谢您的帮助:)
const getForecast = async (api) => {
try {
const res = await axios.get(api);
console.log(res);
const weather1 = res.data.list[0].weather[0].main;
const time1 = res.data.list[0].dt_txt.substr(11, 15);
const weather2 = res.data.list[1].weather[0].main;
const time2 = res.data.list[1].dt_txt.substr(11, 15);
const weather3 = res.data.list[2].weather[0].main;
const time3 = res.data.list[2].dt_txt.substr(11, 15);
const weather4 = res.data.list[3].weather[0].main;
const time4 = res.data.list[3].dt_txt.substr(11, 15);
forecastTime1.textContent = time1;
forecastTime2.textContent = time2;
forecastTime3.textContent = time3;
forecastTime4.textContent = time4;
if (weather1 === "Thunderstorm") {
forecastDisplay1.src = `img/thunder.svg`;
} else if (weather1 === "Drizzle") {
forecastDisplay1.src = `img/drizzle.svg`;
} else if (weather1 === "Rain") {
forecastDisplay1.src = `img/rain.svg`;
} else if (weather1 === "Snow") {
forecastDisplay1.src = `img/snowy.svg`;
} else if (
weather1 === "Mist" ||
weather1 === "Smoke" ||
weather1 === "Haze" ||
weather1 === "Dust" ||
weather1 === "Fog" ||
weather1 === "Sand" ||
weather1 === "Ash" ||
weather1 === "Squall" ||
weather1 === "Tornado"
) {
forecastDisplay1.src = `img/cloudy.svg`;
} else if (weather1 === "Clear") {
forecastDisplay1.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather1 === "Clouds") {
forecastDisplay1.src = `img/cloudy.svg`;
}
if (weather2 === "Thunderstorm") {
forecastDisplay2.src = `img/thunder.svg`;
} else if (weather2 === "Drizzle") {
forecastDisplay.src = `img/drizzle.svg`;
} else if (weather2 === "Rain") {
forecastDisplay2.src = `img/rain.svg`;
} else if (weather2 === "Snow") {
forecastDisplay2.src = `img/snowy.svg`;
} else if (
weather2 === "Mist" ||
weather2 === "Smoke" ||
weather2 === "Haze" ||
weather2 === "Dust" ||
weather2 === "Fog" ||
weather2 === "Sand" ||
weather2 === "Ash" ||
weather2 === "Squall" ||
weather2 === "Tornado"
) {
forecastDisplay2.src = `img/cloudy.svg`;
} else if (weather2 === "Clear") {
forecastDisplay2.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather2 === "Clouds") {
forecastDisplay2.src = `img/cloudy.svg`;
}
if (weather3 === "Thunderstorm") {
forecastDisplay3.src = `img/thunder.svg`;
} else if (weather3 === "Drizzle") {
forecastDisplay3.src = `img/drizzle.svg`;
} else if (weather3 === "Rain") {
forecastDisplay3.src = `img/rain.svg`;
} else if (weather3 === "Snow") {
forecastDisplay3.src = `img/snowy.svg`;
} else if (
weather3 === "Mist" ||
weather3 === "Smoke" ||
weather3 === "Haze" ||
weather3 === "Dust" ||
weather3 === "Fog" ||
weather3 === "Sand" ||
weather3 === "Ash" ||
weather3 === "Squall" ||
weather3 === "Tornado"
) {
forecastDisplay3.src = `img/cloudy.svg`;
} else if (weather3 === "Clear") {
forecastDisplay3.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather3 === "Clouds") {
forecastDisplay3.src = `img/cloudy.svg`;
}
if (weather4 === "Thunderstorm") {
forecastDisplay4.src = `img/thunder.svg`;
} else if (weather4 === "Drizzle") {
forecastDisplay4.src = `img/drizzle.svg`;
} else if (weather4 === "Rain") {
forecastDisplay4.src = `img/rain.svg`;
} else if (weather4 === "Snow") {
forecastDisplay4.src = `img/snowy.svg`;
} else if (
weather4 === "Mist" ||
weather4 === "Smoke" ||
weather4 === "Haze" ||
weather4 === "Dust" ||
weather4 === "Fog" ||
weather4 === "Sand" ||
weather4 === "Ash" ||
weather4 === "Squall" ||
weather4 === "Tornado"
) {
forecastDisplay4.src = `img/cloudy.svg`;
} else if (weather4 === "Clear") {
forecastDisplay4.src = `img/clear-${getDayOrNight()}.svg`;
} else if (weather4 === "Clouds") {
forecastDisplay4.src = `img/cloudy.svg`;
}
} catch (e) {
console.log(e);
}
};
为什么不使用 switch 语句而不是 if/else statements.Its 更简单,更少 code.https://www.w3schools.com/js/js_switch.asp
我可能会做类似下面的事情。永远不要使用具有相同名称的变量,只是一个数字来区分它们,而是使用数组或类似数组的结构,这样你就可以遍历它们:
// This is not defined in the snippet you showed us, but it makes it easier to loop
const forecastTime = document.querySelectorAll('.forecast-time'),
forecastDisplay = document.querySelectorAll('.forecast-display');
const res = await axios.get(api);
res.data.list.slice(0, 4) // If there are more than 4, keep the first 4?
.forEach(({ weather, dt_txt }, i) => {
forecastTime[i].textContent = dt_txt.substr(11, 15);
forecastDisplay[i].src = getImageForWeatherType(weather[0].main);
});
function getImageForWeatherType(type) {
if (type === "Clear") { return `img/clear-${getDayOrNight()}.svg`; } // Special case
const imageMap = {
`img/thunder.svg`: ['Thunderstorm'],
`img/drizzle.svg`: ['Drizzle'],
`img/rain.svg`: ['Rain'],
`img/snowy.svg`: ['Snow'],
`img/cloudy.svg`: ["Mist", "Smoke", "Haze", "Dust", "Fog", "Sand",
"Ash", "Squall", "Tornado", "Clouds"]
};
return Object.keys(imageMap).find(key => imageMap[key].includes(type));
}
你可以使用这个模式:
const getForecast = async (api) => {
const map_weather_img = {
'Thunderstorm': 'img/thunder.svg',
'Drizzle': 'img/drizzle.svg',
'Rain': 'img/rain.svg',
'Snow': 'img/snowy.svg',
'Mist': 'img/cloudy.svg',
'Smoke': 'img/cloudy.svg',
'Haze': 'img/cloudy.svg',
'Dust': 'img/cloudy.svg',
'Fog': 'img/cloudy.svg',
'Sand': 'img/cloudy.svg',
'Ash': 'img/cloudy.svg',
'Squall': 'img/cloudy.svg',
'Tornado': 'img/cloudy.svg',
'Clear': `img/clear-${getDayOrNight()}.svg`,
'Clouds': 'img/cloudy.svg',
};
try {
const res = await axios.get(api);
console.log(res);
const weather1 = res.data.list[0].weather[0].main;
const time1 = res.data.list[0].dt_txt.substr(11, 15);
const weather2 = res.data.list[1].weather[0].main;
const time2 = res.data.list[1].dt_txt.substr(11, 15);
const weather3 = res.data.list[2].weather[0].main;
const time3 = res.data.list[2].dt_txt.substr(11, 15);
const weather4 = res.data.list[3].weather[0].main;
const time4 = res.data.list[3].dt_txt.substr(11, 15);
forecastTime1.textContent = time1;
forecastTime2.textContent = time2;
forecastTime3.textContent = time3;
forecastTime4.textContent = time4;
forecastDisplay1.src = map_weather_img[weather1];
forecastDisplay2.src = map_weather_img[weather2];
forecastDisplay3.src = map_weather_img[weather3];
forecastDisplay4.src = map_weather_img[weather4];
} catch (e) {
console.log(e);
}
};
但为了更灵活,您可以使用这个:
// array of HTML Element
const forecast = [
{
display: /*HTML element*/,
time: /*HTML element*/,
},
{
display: /*HTML element*/,
time: /*HTML element*/,
},
...
];
const getForecast = async (api) => {
const table = {
'Thunderstorm': 'img/thunder.svg',
'Drizzle': 'img/drizzle.svg',
'Rain': 'img/rain.svg',
'Snow': 'img/snowy.svg',
'Mist': 'img/cloudy.svg',
'Smoke': 'img/cloudy.svg',
'Haze': 'img/cloudy.svg',
'Dust': 'img/cloudy.svg',
'Fog': 'img/cloudy.svg',
'Sand': 'img/cloudy.svg',
'Ash': 'img/cloudy.svg',
'Squall': 'img/cloudy.svg',
'Tornado': 'img/cloudy.svg',
'Clear': `img/clear-${getDayOrNight()}.svg`,
'Clouds': 'img/cloudy.svg',
};
try {
const res = await axios.get(api);
console.log(res);
forecast.forEach( (f,i) => {
const weather = res.data.list[i].weather[0].main;
const time = res.data.list[i].dt_txt.substr(11, 15);
f.time.textContent = time;
f.display.src = table[weather];
});
} catch (e) {
console.log(e);
}
};