4. Explore the features of ES6 like arrow functions, callbacks, promises, async/await.
Implement
an application for reading the weather information from openweathermap.org and display the
information in the form of a graph on the web page.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Weather App with ES6 Features</title>
<link rel="stylesheet" href="styles.css">
<!-- Chart.js for data visualization -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
<div class="container">
<h1>Weather App with ES6 Features</h1>
<div class="search-container">
<input type="text" id="city-input" placeholder="Enter city name">
<button id="search-btn">Search</button>
</div>
<div class="weather-container">
<div id="current-weather" class="weather-card">
<h2>Current Weather</h2>
<div id="weather-info"></div>
</div>
<div id="weather-chart-container">
<canvas id="weather-chart"></canvas>
</div>
</div>
<div class="es6-demo-container">
<h2>ES6 Features Demo</h2>
<div class="feature-section">
<h3>Arrow Functions</h3>
<button id="arrow-demo-btn">Run Demo</button>
<div id="arrow-result" class="result"></div>
</div>
<div class="feature-section">
<h3>Callbacks</h3>
<button id="callback-demo-btn">Run Demo</button>
<div id="callback-result" class="result"></div>
</div>
<div class="feature-section">
<h3>Promises</h3>
<button id="promise-demo-btn">Run Demo</button>
<div id="promise-result" class="result"></div>
</div>
<div class="feature-section">
<h3>Async/Await</h3>
<button id="async-demo-btn">Run Demo</button>
<div id="async-result" class="result"></div>
</div>
</div>
</div>
<script src="es6Features.js"></script>
<script src="weatherApp.js"></script>
</body>
</html>
style.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
}
body {
background-color: #f5f5f5;
color: #333;
line-height: 1.6;
}
.container {
max-width: 1000px;
margin: 0 auto;
padding: 20px;
}
h1 {
text-align: center;
margin-bottom: 30px;
color: #2c3e50;
}
h2 {
color: #3498db;
margin-bottom: 15px;
}
h3 {
color: #2c3e50;
margin-bottom: 10px;
}
.search-container {
display: flex;
justify-content: center;
margin-bottom: 30px;
}
#city-input {
padding: 10px;
width: 300px;
border: 1px solid #ddd;
border-radius: 4px 0 0 4px;
font-size: 16px;
}
#search-btn {
padding: 10px 20px;
background-color: #3498db;
color: white;
border: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
#search-btn:hover {
background-color: #2980b9;
}
.weather-container {
display: flex;
flex-direction: column;
gap: 20px;
margin-bottom: 40px;
}
.weather-card {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
#weather-chart-container {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
height: 300px;
}
.es6-demo-container {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.feature-section {
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.feature-section:last-child {
border-bottom: none;
}
button {
padding: 8px 15px;
background-color: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-bottom: 10px;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.result {
background-color: #f9f9f9;
padding: 10px;
border-radius: 4px;
border-left: 3px solid #3498db;
min-height: 40px;
white-space: pre-wrap;
}
@media (min-width: 768px) {
.weather-container {
flex-direction: row;
}
.weather-card {
flex: 1;
}
#weather-chart-container {
flex: 2;
}
}
es6Feastures.js
// ES6 Features Demonstration
// ===== Arrow Functions =====
document.getElementById('arrow-demo-btn').addEventListener('click', () => {
const resultElement = document.getElementById('arrow-result');
resultElement.innerHTML = '';
// Traditional function
function traditionalSum(a, b) {
return a + b;
}
// Arrow function
const arrowSum = (a, b) => a + b;
// Arrow function with multiple statements
const arrowMultipleStatements = (a, b) => {
const sum = a + b;
const product = a * b;
return `Sum: ${sum}, Product: ${product}`;
};
// Array methods with arrow functions
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
const filtered = numbers.filter(num => num > 2);
resultElement.innerHTML = `
Traditional function: ${traditionalSum(5, 3)} <br>
Arrow function: ${arrowSum(5, 3)} <br>
Arrow function with multiple statements: ${arrowMultipleStatements(5, 3)}
<br>
Array.map with arrow function: [${doubled}] <br>
Array.filter with arrow function: [${filtered}]
`;
});
// ===== Callbacks =====
document.getElementById('callback-demo-btn').addEventListener('click', () => {
const resultElement = document.getElementById('callback-result');
resultElement.innerHTML = 'Processing...';
// Simulating asynchronous operation with callbacks
const fetchData = (callback) => {
setTimeout(() => {
const data = { name: 'Weather Data', temperature: 25 };
callback(null, data);
}, 1500);
};
const processData = (error, data) => {
if (error) {
resultElement.innerHTML = `Error: ${error.message}`;
} else {
resultElement.innerHTML = `
Callback received after 1.5 seconds: <br>
Name: ${data.name} <br>
Temperature: ${data.temperature}°C
`;
}
};
// Execute the callback pattern
fetchData(processData);
});
// ===== Promises =====
document.getElementById('promise-demo-btn').addEventListener('click', () => {
const resultElement = document.getElementById('promise-result');
resultElement.innerHTML = 'Processing...';
// Creating a promise
const fetchDataPromise = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // Change to false to simulate error
if (success) {
const data = { name: 'Promise Data', temperature: 28 };
resolve(data);
} else {
reject(new Error('Failed to fetch data'));
}
}, 1500);
});
};
// Using the promise
fetchDataPromise()
.then(data => {
resultElement.innerHTML = `
Promise resolved after 1.5 seconds: <br>
Name: ${data.name} <br>
Temperature: ${data.temperature}°C
`;
})
.catch(error => {
resultElement.innerHTML = `Promise rejected: ${error.message}`;
})
.finally(() => {
console.log('Promise operation completed');
});
});
// ===== Async/Await =====
document.getElementById('async-demo-btn').addEventListener('click', async () => {
const resultElement = document.getElementById('async-result');
resultElement.innerHTML = 'Processing...';
// Function that returns a promise
const fetchDataAsync = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // Change to false to simulate error
if (success) {
const data = { name: 'Async/Await Data', temperature: 30 };
resolve(data);
} else {
reject(new Error('Failed to fetch data'));
}
}, 1500);
});
};
// Using async/await
try {
const data = await fetchDataAsync();
resultElement.innerHTML = `
Async/Await resolved after 1.5 seconds: <br>
Name: ${data.name} <br>
Temperature: ${data.temperature}°C
`;
} catch (error) {
resultElement.innerHTML = `Async/Await error: ${error.message}`;
}
});
weatherApp.js
// Weather App Implementation using ES6 Features
// Constants
const API_KEY = '349e1822e8739db21980838d35c0354a'; // You need to get your API
key from OpenWeatherMap
const BASE_URL = 'https://api.openweathermap.org/data/2.5';
// DOM Elements
const cityInput = document.getElementById('city-input');
const searchBtn = document.getElementById('search-btn');
const weatherInfo = document.getElementById('weather-info');
const weatherChartCanvas = document.getElementById('weather-chart');
// Chart instance
let weatherChart = null;
// Event Listeners
searchBtn.addEventListener('click', () => {
const city = cityInput.value.trim();
if (city) {
getWeatherData(city);
} else {
alert('Please enter a city name');
}
});
cityInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
searchBtn.click();
}
});
// Weather API Functions using ES6 Features
// Fetch current weather data using async/await
const getWeatherData = async (city) => {
try {
weatherInfo.innerHTML = 'Loading...';
// Using template literals for URL construction
const currentWeatherUrl =
`${BASE_URL}/weather?q=${city}&units=metric&appid=${API_KEY}`;
const forecastUrl =
`${BASE_URL}/forecast?q=${city}&units=metric&appid=${API_KEY}`;
// Using Promise.all to fetch multiple resources in parallel
const [currentResponse, forecastResponse] = await Promise.all([
fetch(currentWeatherUrl),
fetch(forecastUrl)
]);
// Check if responses are ok
if (!currentResponse.ok || !forecastResponse.ok) {
throw new Error('City not found or API error');
}
// Parse JSON responses using arrow functions and await
const currentData = await currentResponse.json();
const forecastData = await forecastResponse.json();
// Display the data
displayCurrentWeather(currentData);
displayWeatherChart(forecastData);
} catch (error) {
weatherInfo.innerHTML = `Error: ${error.message}`;
clearChart();
}
};
// Display current weather information
const displayCurrentWeather = (data) => {
// Destructuring assignment to extract properties
const { name, main, weather, wind, sys } = data;
const { temp, feels_like, humidity, pressure } = main;
const { description, icon } = weather[0];
// Template literals for HTML construction
const html = `
<div class="weather-details">
<h3>${name}, ${sys.country}</h3>
<div class="weather-icon">
<img src="https://openweathermap.org/img/wn/${icon}@2x.png"
alt="${description}">
</div>
<div class="temperature">${Math.round(temp)}°C</div>
<div class="description">${description}</div>
<div class="details">
<p>Feels like: ${Math.round(feels_like)}°C</p>
<p>Humidity: ${humidity}%</p>
<p>Pressure: ${pressure} hPa</p>
<p>Wind: ${wind.speed} m/s</p>
</div>
</div>
`;
weatherInfo.innerHTML = html;
};
// Display weather forecast chart
const displayWeatherChart = (data) => {
// Clear previous chart
clearChart();
// Process forecast data
// Using array methods (map, filter) with arrow functions
const forecastList = data.list;
// Get the next 5 days data at the same time of day
const filteredForecast = forecastList.filter((item, index) => index % 8 ===
0);
// Extract dates and temperatures using destructuring and map
const labels = filteredForecast.map(item => {
const date = new Date(item.dt * 1000);
return date.toLocaleDateString('en-US', { weekday: 'short' });
});
const temperatures = filteredForecast.map(item => item.main.temp);
const minTemps = filteredForecast.map(item => item.main.temp_min);
const maxTemps = filteredForecast.map(item => item.main.temp_max);
// Create chart using Chart.js
weatherChart = new Chart(weatherChartCanvas, {
type: 'line',
data: {
labels: labels,
datasets: [
{
label: 'Temperature (°C)',
data: temperatures,
borderColor: '#3498db',
backgroundColor: 'rgba(52, 152, 219, 0.2)',
tension: 0.3,
fill: true
},
{
label: 'Min Temperature (°C)',
data: minTemps,
borderColor: '#2980b9',
backgroundColor: 'rgba(41, 128, 185, 0.1)',
borderDash: [5, 5],
tension: 0.3,
fill: false
},
{
label: 'Max Temperature (°C)',
data: maxTemps,
borderColor: '#e74c3c',
backgroundColor: 'rgba(231, 76, 60, 0.1)',
borderDash: [5, 5],
tension: 0.3,
fill: false
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: '5-Day Weather Forecast',
font: {
size: 16
}
},
tooltip: {
mode: 'index',
intersect: false
}
},
scales: {
y: {
title: {
display: true,
text: 'Temperature (°C)'
}
}
}
}
});
};
// Clear the chart
const clearChart = () => {
if (weatherChart) {
weatherChart.destroy();
weatherChart = null;
}
};
// Initial instructions
weatherInfo.innerHTML = `
<div class="initial-message">
<p>Enter a city name and click "Search" to get weather information.</p>
<p>You'll need to add your OpenWeatherMap API key in the weatherApp.js
file.</p>
</div>
`;
// Display a message about getting an API key
console.log('Remember to get your API key from https://openweathermap.org/api and
add it to the weatherApp.js file.');
Output:
Open Index.html page with Browser
file:///C:/Users/rames/OneDrive/1.PEC/2-2/LabPrograms/4/index.html
Type Hyderabad Search
Demo