JavaScript异步编程实战:构建智能天气预报应用 | 前端开发教程

基于JavaScript异步编程技术实现




技术特性展示

Promise异步处理

使用Promise管理多个异步操作,确保数据获取和处理的顺序性

async/await语法

使用现代async/await语法简化异步代码,提高可读性

Fetch API调用

使用Fetch API进行HTTP请求,获取实时天气数据

// 天气API配置(使用模拟数据,实际项目中替换为真实API)
const WEATHER_API = {
baseUrl: ‘https://api.openweathermap.org/data/2.5/weather’,
// 注意:实际使用时需要申请API密钥
apiKey: ‘your_api_key_here’
};

// DOM元素引用
const cityInput = document.getElementById(‘cityInput’);
const searchBtn = document.getElementById(‘searchBtn’);
const locationBtns = document.querySelectorAll(‘.location-btn’);
const loadingElement = document.getElementById(‘loading’);
const weatherInfoElement = document.getElementById(‘weatherInfo’);
const errorMessageElement = document.getElementById(‘errorMessage’);

// 模拟天气数据(实际项目中使用真实API)
const mockWeatherData = {
‘北京’: {
name: ‘北京’,
main: {
temp: 22,
feels_like: 23,
humidity: 65
},
weather: [{ description: ‘晴朗’, main: ‘Clear’, icon: ’01d’ }],
wind: { speed: 3.5 }
},
‘上海’: {
name: ‘上海’,
main: {
temp: 25,
feels_like: 27,
humidity: 70
},
weather: [{ description: ‘多云’, main: ‘Clouds’, icon: ’03d’ }],
wind: { speed: 4.2 }
},
‘广州’: {
name: ‘广州’,
main: {
temp: 28,
feels_like: 31,
humidity: 75
},
weather: [{ description: ‘小雨’, main: ‘Rain’, icon: ’10d’ }],
wind: { speed: 2.8 }
},
‘深圳’: {
name: ‘深圳’,
main: {
temp: 29,
feels_like: 32,
humidity: 80
},
weather: [{ description: ‘雷阵雨’, main: ‘Thunderstorm’, icon: ’11d’ }],
wind: { speed: 3.1 }
}
};

// 工具函数:显示加载状态
function showLoading() {
hideElements([weatherInfoElement, errorMessageElement]);
loadingElement.classList.remove(‘hidden’);
}

// 工具函数:隐藏元素
function hideElements(elements) {
elements.forEach(element => {
if (element) element.classList.add(‘hidden’);
});
}

// 工具函数:显示错误信息
function showError(message) {
hideElements([loadingElement, weatherInfoElement]);
errorMessageElement.innerHTML = `

获取天气数据失败

${message}

`;
errorMessageElement.classList.remove(‘hidden’);

// 添加重试按钮事件监听
document.getElementById(‘retryBtn’).addEventListener(‘click’, () => {
const lastCity = cityInput.value || ‘北京’;
getWeatherData(lastCity);
});
}

// 模拟API延迟
function simulateAPIDelay() {
return new Promise(resolve => {
setTimeout(resolve, 1000 + Math.random() * 1000);
});
}

// 获取天气数据(模拟实现)
async function getWeatherData(cityName) {
showLoading();

try {
// 模拟API调用延迟
await simulateAPIDelay();

// 模拟API响应
if (mockWeatherData[cityName]) {
displayWeatherData(mockWeatherData[cityName]);
} else {
// 模拟随机天气数据
const weatherConditions = [
{ description: ‘晴朗’, main: ‘Clear’, icon: ’01d’ },
{ description: ‘多云’, main: ‘Clouds’, icon: ’03d’ },
{ description: ‘小雨’, main: ‘Rain’, icon: ’10d’ },
{ description: ‘雷阵雨’, main: ‘Thunderstorm’, icon: ’11d’ }
];

const randomCondition = weatherConditions[Math.floor(Math.random() * weatherConditions.length)];

const mockData = {
name: cityName,
main: {
temp: 15 + Math.floor(Math.random() * 20),
feels_like: 15 + Math.floor(Math.random() * 20),
humidity: 50 + Math.floor(Math.random() * 40)
},
weather: [randomCondition],
wind: { speed: 1 + Math.random() * 5 }
};

displayWeatherData(mockData);
}
} catch (error) {
showError(`网络请求失败: ${error.message}`);
}
}

// 显示天气数据
function displayWeatherData(data) {
hideElements([loadingElement, errorMessageElement]);

const temperature = Math.round(data.main.temp);
const feelsLike = Math.round(data.main.feels_like);
const humidity = data.main.humidity;
const description = data.weather[0].description;
const windSpeed = data.wind.speed;

// 根据天气状况选择图标
let weatherIcon = ‘fa-sun’;
if (description.includes(‘雨’)) weatherIcon = ‘fa-cloud-rain’;
else if (description.includes(‘云’)) weatherIcon = ‘fa-cloud’;
else if (description.includes(‘雷’)) weatherIcon = ‘fa-bolt’;

weatherInfoElement.innerHTML = `

${data.name}天气

${temperature}°C
${description}

体感温度: ${feelsLike}°C

湿度: ${humidity}%

风速: ${windSpeed} m/s

`;

weatherInfoElement.classList.remove(‘hidden’);
}

// 事件监听器设置
function setupEventListeners() {
// 搜索按钮点击事件
searchBtn.addEventListener(‘click’, () => {
const city = cityInput.value.trim();
if (city) {
getWeatherData(city);
} else {
showError(‘请输入城市名称’);
}
});

// 回车键搜索
cityInput.addEventListener(‘keypress’, (e) => {
if (e.key === ‘Enter’) {
searchBtn.click();
}
});

// 城市快捷按钮点击事件
locationBtns.forEach(btn => {
btn.addEventListener(‘click’, () => {
const city = btn.getAttribute(‘data-city’);
cityInput.value = city;
getWeatherData(city);
});
});
}

// 页面加载完成后初始化
document.addEventListener(‘DOMContentLoaded’, () => {
setupEventListeners();
// 默认显示北京天气
getWeatherData(‘北京’);
});

/* 基础样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif;
}

body {
background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%);
color: #2d3436;
min-height: 100vh;
padding: 20px;
}

.container {
max-width: 1000px;
margin: 0 auto;
}

/* 应用头部样式 */
.app-header {
text-align: center;
margin-bottom: 30px;
color: white;
}

.app-header h1 {
font-size: 2.5rem;
margin-bottom: 10px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3);
}

.app-header p {
font-size: 1.2rem;
opacity: 0.9;
}

/* 搜索区域样式 */
.search-section {
background: white;
border-radius: 15px;
padding: 25px;
margin-bottom: 30px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.search-container {
display: flex;
margin-bottom: 20px;
}

#cityInput {
flex: 1;
padding: 12px 15px;
border: 2px solid #ddd;
border-radius: 8px 0 0 8px;
font-size: 1rem;
outline: none;
transition: border-color 0.3s;
}

#cityInput:focus {
border-color: #74b9ff;
}

#searchBtn {
background: #0984e3;
color: white;
border: none;
padding: 12px 20px;
border-radius: 0 8px 8px 0;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
transition: background 0.3s;
}

#searchBtn:hover {
background: #0770c4;
}

.location-buttons {
display: flex;
flex-wrap: wrap;
gap: 10px;
}

.location-btn {
background: #f1f2f6;
border: none;
padding: 8px 15px;
border-radius: 20px;
cursor: pointer;
transition: all 0.3s;
}

.location-btn:hover {
background: #dfe4ea;
transform: translateY(-2px);
}

/* 加载状态样式 */
.loading {
text-align: center;
padding: 40px;
color: white;
}

.spinner {
border: 5px solid rgba(255,255,255,0.3);
border-radius: 50%;
border-top: 5px solid white;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

/* 天气信息样式 */
.weather-info {
margin-bottom: 30px;
}

.weather-card {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.weather-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
border-bottom: 1px solid #eee;
padding-bottom: 15px;
}

.weather-icon {
font-size: 3rem;
color: #74b9ff;
}

.temperature {
font-size: 3rem;
font-weight: bold;
color: #2d3436;
margin-bottom: 10px;
}

.description {
font-size: 1.5rem;
color: #636e72;
margin-bottom: 20px;
}

.details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 20px;
}

.detail-item {
display: flex;
align-items: center;
gap: 10px;
}

.detail-item i {
color: #74b9ff;
width: 20px;
}

.weather-footer {
border-top: 1px solid #eee;
padding-top: 15px;
color: #636e72;
font-size: 0.9rem;
}

/* 错误信息样式 */
.error-message {
background: #ff7675;
color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 30px;
text-align: center;
}

.error-content i {
font-size: 2rem;
margin-bottom: 10px;
}

.retry-btn {
background: white;
color: #ff7675;
border: none;
padding: 8px 15px;
border-radius: 5px;
cursor: pointer;
margin-top: 10px;
font-weight: 600;
}

/* 特性展示区域 */
.features-section {
background: white;
border-radius: 15px;
padding: 25px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

.features-section h2 {
text-align: center;
margin-bottom: 25px;
color: #2d3436;
}

.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}

.feature-card {
text-align: center;
padding: 20px;
border-radius: 10px;
background: #f8f9fa;
transition: transform 0.3s;
}

.feature-card:hover {
transform: translateY(-5px);
}

.feature-card i {
font-size: 2.5rem;
color: #74b9ff;
margin-bottom: 15px;
}

.feature-card h3 {
margin-bottom: 10px;
color: #2d3436;
}

/* 响应式设计 */
@media (max-width: 768px) {
.search-container {
flex-direction: column;
}

#cityInput {
border-radius: 8px;
margin-bottom: 10px;
}

#searchBtn {
border-radius: 8px;
}

.app-header h1 {
font-size: 2rem;
}

.temperature {
font-size: 2.5rem;
}
}

/* 辅助类 */
.hidden {
display: none !important;
}

JavaScript异步编程实战:构建智能天气预报应用 | 前端开发教程
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

淘吗网 javascript JavaScript异步编程实战:构建智能天气预报应用 | 前端开发教程 https://www.taomawang.com/web/javascript/1121.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务