Project: A School Weather Report
Project: A School Weather Report
An API-driven report needs loading, success and failure behavior. This deterministic response teaches data extraction without an API key; the practical request section shows how real fetch connects to an endpoint.
Before this topic, review Project: A Homework List if its terms are unfamiliar.
What you’ll learn
- Explain project: a school weather report through the school example.
- Trace the shown operations and distinguish their result from displayed output.
- Make the practice change and explain its consequence: The validated temperature changes and the success view reflects it.
Work through the school example
This is JavaScript in a browser. Read the initial values, then follow each operation to its displayed result. A declaration names a value, a function call performs an operation, and console.log displays its arguments.
Create this markup in a separate index.html, then place the JavaScript in a script after these elements. Use this isolated practice page so the selectors refer to its markup.
<p id="weather">Loading</p>JavaScript · browser · complete script for the supplied markup
async function report() {
try {
const response = new Response('{"temperature":24}', { status: 200 });
if (!response.ok) throw new Error("Weather unavailable");
const data = await response.json();
if (!Number.isFinite(data.temperature)) throw new Error("Invalid temperature");
document.querySelector("#weather").textContent = data.temperature + " C";
console.log(document.querySelector("#weather").textContent);
} catch (error) {
document.querySelector("#weather").textContent = error.message;
}
}
report();
Expected output
24 COverview
This project will help you build a Weather App using pure JavaScript and an external API. We will use the OpenWeatherMap API to fetch real-time weather data based on the user's city input.
What You'll Learn
- How to make HTTP requests using
fetch() - How to parse and handle JSON data
- How to build a CLI or console-based tool using JavaScript
- How to use environment variables to store API keys (Node.js only)
Step 1: Get API Access
Sign up at OpenWeatherMap and get your free API key.
Step 2: Understand the API Request
The API URL to get weather for a city looks like this:
https://api.openweathermap.org/data/2.5/weather?q=London&appid=YOUR_API_KEY&units=metric
Question:
What are the parameters in the API URL?
Answer: q is the city name, appid is your API key, and units=metric ensures temperature is in Celsius.
Step 3: Write JavaScript Code (Browser Console)
This version runs directly in the browser console. Replace YOUR_API_KEY with your actual key.
const city = "Delhi";
const apiKey = "YOUR_API_KEY"; // Replace with your real API key
fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric`)
.then(response => {
if (!response.ok) {
throw new Error("City not found");
}
return response.json();
})
.then(data => {
console.log(`Weather in ${data.name}:`);
console.log(`Temperature: ${data.main.temp}°C`);
console.log(`Weather: ${data.weather[0].description}`);
console.log(`Humidity: ${data.main.humidity}%`);
console.log(`Wind Speed: ${data.wind.speed} m/s`);
})
.catch(error => {
console.error("Error fetching weather data:", error.message);
});
Weather in Delhi: Temperature: 32°C Weather: clear sky Humidity: 28% Wind Speed: 3.6 m/s
Code Description
fetch()is used to send a GET request to the weather API.- We check
response.okto handle invalid cities or errors. data.main.temp,data.weather[0].descriptionetc. extract key weather metrics.- Error handling with
.catch()ensures graceful failure.
Question:
What happens if the user enters an invalid city name?
Answer: The API returns a 404 status, and our code throws an error with the message "City not found".
Step 4: Run in Node.js (with Readline)
This version lets users enter city names via command line:
// weather.js
const readline = require("readline");
const https = require("https");
const apiKey = "YOUR_API_KEY"; // Replace with your key
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("Enter a city name: ", function(city) {
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric`;
https.get(url, (res) => {
let data = "";
res.on("data", chunk => data += chunk);
res.on("end", () => {
const weather = JSON.parse(data);
if (weather.cod !== 200) {
console.error("Error:", weather.message);
} else {
console.log(`Weather in ${weather.name}:`);
console.log(`Temperature: ${weather.main.temp}°C`);
console.log(`Condition: ${weather.weather[0].description}`);
}
rl.close();
});
}).on("error", (e) => {
console.error("Failed to fetch:", e.message);
rl.close();
});
});
Enter a city name: Paris Weather in Paris: Temperature: 21°C Condition: few clouds
Best Practices
- Always validate API responses before accessing nested properties.
- Store API keys securely (e.g., in
.envfor real-world apps). - Handle network errors and empty inputs gracefully.
Wrap-up
This project helped you connect JavaScript to a real-world weather API. You now know how to fetch, parse, and display data dynamically using modern JavaScript techniques.
Recognize the important boundary
The fixed response is not live weather. Real services have units, quotas, credentials and response contracts; do not expose private service keys in browser source.
Try a small variation
JavaScript · original source for practice
async function report() {
try {
const response = new Response('{"temperature":24}', { status: 200 });
if (!response.ok) throw new Error("Weather unavailable");
const data = await response.json();
if (!Number.isFinite(data.temperature)) throw new Error("Invalid temperature");
document.querySelector("#weather").textContent = data.temperature + " C";
console.log(document.querySelector("#weather").textContent);
} catch (error) {
document.querySelector("#weather").textContent = error.message;
}
}
report();
Your task: Replace "temperature":24 with "temperature":28. Predict the result before running the edited program.
The source is repeated here. If the edit targets the HTML rather than the script, use the markup repeated below; the worked answer also repeats the changed markup.
Markup used by this section:
<p id="weather">Loading</p>Worked answer and reasoning
The validated temperature changes and the success view reflects it.
Markup for this edited program:
<p id="weather">Loading</p>JavaScript · complete worked variation
async function report() {
try {
const response = new Response('{"temperature":28}', { status: 200 });
if (!response.ok) throw new Error("Weather unavailable");
const data = await response.json();
if (!Number.isFinite(data.temperature)) throw new Error("Invalid temperature");
document.querySelector("#weather").textContent = data.temperature + " C";
console.log(document.querySelector("#weather").textContent);
} catch (error) {
document.querySelector("#weather").textContent = error.message;
}
}
report();
Expected output
28 CPredict the original program
JavaScript · original program for this question
async function report() {
try {
const response = new Response('{"temperature":24}', { status: 200 });
if (!response.ok) throw new Error("Weather unavailable");
const data = await response.json();
if (!Number.isFinite(data.temperature)) throw new Error("Invalid temperature");
document.querySelector("#weather").textContent = data.temperature + " C";
console.log(document.querySelector("#weather").textContent);
} catch (error) {
document.querySelector("#weather").textContent = error.message;
}
}
report();
Markup used by this section:
<p id="weather">Loading</p>Connect the response to a real request
This example makes a real same-origin HTTP request. Provide /__javascript-api/student on your own practice server with JSON such as {"marks":72}. This teaching endpoint is used by the verification server; it is not a public API on the deployed course. A successful response prints 72; HTTP and invalid-data failures enter catch.
For a POST, use fetch(endpoint, {method:"POST", headers:{"Content-Type":"application/json"}, body:JSON.stringify({marks:72})}). The endpoint must implement that contract. Do not retry writes without understanding duplicate processing.
JavaScript · browser · real HTTP request with a practice endpoint
async function loadReport() {
try {
const response = await fetch('/__javascript-api/student');
if (!response.ok) throw new Error('HTTP ' + response.status);
const student = await response.json();
if (!Number.isFinite(student.marks)) throw new Error('Invalid mark');
console.log(student.marks);
} catch (error) { console.log(error.message); }
}
loadReport();Expected output
72Keep the useful idea
An API-driven report needs loading, success and failure behavior. This deterministic response teaches data extraction without an API key; the practical request section shows how real fetch connects to an endpoint.
Check your variation against this explanation: The validated temperature changes and the success view reflects it.
Use the JavaScript array reference library for individual array operations and boundary tests to check a rule independently.
Reaching the recap and completing the quizzes are separate milestones.