JSJavaScript · Lesson 8 of 14

Mini Project: Fetch & Display Data

Let's build a real Node.js script that fetches data from a public API and displays it nicely. Networks, JSON, async/await — all in one.

JavaScript
// weather.js — Fetches weather from Open-Meteo (free, no API key)
// Run: node weather.js

async function getWeather(city) {
  // Step 1: Geocode the city name to coordinates
  const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1`;
  const geoRes = await fetch(geoUrl);
  const geoData = await geoRes.json();

  if (!geoData.results?.length) {
    throw new Error(`City not found: ${city}`);
  }

  const { latitude, longitude, name, country } = geoData.results[0];

  // Step 2: Fetch weather data
  const weatherUrl = `https://api.open-meteo.com/v1/forecast`
    + `?latitude=${latitude}&longitude=${longitude}`
    + `&current=temperature_2m,wind_speed_10m,weather_code`;

  const weatherRes = await fetch(weatherUrl);
  const weatherData = await weatherRes.json();

  const current = weatherData.current;

  return {
    city: `${name}, ${country}`,
    temp: current.temperature_2m,
    wind: current.wind_speed_10m,
  };
}

function formatWeather(data) {
  const lines = [
    `📍 ${data.city}`,
    `🌡  Temperature: ${data.temp}°C`,
    `💨  Wind: ${data.wind} km/h`,
  ];
  return lines.join("\n");
}

async function main() {
  const cities = process.argv.slice(2);

  if (cities.length === 0) {
    console.log("Usage: node weather.js <city> [city2] ...");
    console.log("Example: node weather.js London Paris Berlin");
    process.exit(1);
  }

  const results = await Promise.allSettled(
    cities.map(city => getWeather(city))
  );

  results.forEach((result, i) => {
    if (result.status === "fulfilled") {
      console.log(formatWeather(result.value));
    } else {
      console.error(`Error for ${cities[i]}: ${result.reason.message}`);
    }
    console.log("");
  });
}

main().catch(console.error);

This script uses Promise.allSettled() instead of Promise.all() — the difference is that allSettled waits for ALL promises to finish, even if some fail, while Promise.all() rejects immediately if any promise fails. For fetching multiple items where partial results are acceptable, allSettled is the right choice.

Bash
node weather.js London Paris Tokyo Berlin