Aller au contenu
← 1001 Widgets
N° 013 · ●●●

Météo

La météo d'une ville en direct, sans clé d'API, grâce à Open-Meteo. Le bon exercice pour apprendre à attendre une réponse du réseau et à gérer ses erreurs.

HTMLJSAPI
Ce qu'on apprend
  • Appeler une API avec fetch et async/await
  • Enchaîner deux requêtes : la ville, puis la météo
  • Afficher une erreur claire quand le réseau lâche
Pourquoi ce langage

Pourquoi un widget météo ? C'est la première rencontre avec une API : on envoie une requête, on attend, on reçoit du JSON, et on gère le cas où rien n'arrive.

On utilise Open-Meteo, une API gratuite et sans clé : parfait pour apprendre sans créer de compte.

Pourquoi en JavaScript simple ? fetch, async et await suffisent. Le reste, c'est de l'affichage.

Comment ça marche
  1. LE HTML

    <form id="recherche">
      <input id="ville" value="Bruxelles">
      <button>Voir</button>
    </form>
    <p id="meteo" aria-live="polite"></p>
  2. TROUVER LA VILLE

    Open-Meteo a deux API : une pour transformer un nom de ville en coordonnées, une pour la météo.

    async function coordonnees(nom) {
      const r = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(nom)}&count=1&language=fr`);
      if (!r.ok) throw new Error('Recherche indisponible');
      const data = await r.json();
      if (!data.results) throw new Error('Ville introuvable');
      return data.results[0];
    }
  3. LIRE LA MÉTÉO

    async function meteo({ latitude, longitude }) {
      const r = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&current=temperature_2m,weather_code,wind_speed_10m`);
      if (!r.ok) throw new Error('Météo indisponible');
      return (await r.json()).current;
    }
  4. TRADUIRE LE CODE MÉTÉO

    L'API renvoie un numéro par type de temps.

    const CIELS = { 0: 'Ciel dégagé', 1: 'Plutôt dégagé', 2: 'Partiellement nuageux', 3: 'Couvert', 45: 'Brouillard', 61: 'Pluie', 71: 'Neige', 80: 'Averses', 95: 'Orage' };
  5. TOUT ASSEMBLER

    try / catch attrape aussi bien une ville introuvable qu'une coupure réseau.

    document.getElementById('recherche').addEventListener('submit', async e => {
      e.preventDefault();
      const sortie = document.getElementById('meteo');
      sortie.textContent = 'Chargement…';
      try {
        const lieu = await coordonnees(document.getElementById('ville').value);
        const m = await meteo(lieu);
        sortie.textContent = `${lieu.name} : ${Math.round(m.temperature_2m)} °C, ${CIELS[m.weather_code] ?? 'temps variable'}, vent ${Math.round(m.wind_speed_10m)} km/h`;
      } catch (err) {
        sortie.textContent = err.message;
      }
    });
Pièges

PIÈGE 1 : Oublier que le réseau peut échouer

Piège

Mauvais : un fetch sans try / catch. Hors connexion, le widget reste bloqué sur « Chargement ».

Fix

Correct : try / catch autour des appels, et un message clair.

PIÈGE 2 : Croire que fetch échoue sur une erreur 500

Piège

Mauvais : se fier au catch seul. fetch ne lève une erreur que si le réseau tombe : une réponse 404 ou 500 passe sans bruit.

Fix

Correct : tester r.ok avant de lire le JSON.

PIÈGE 3 : Coller le texte tapé dans l'URL

Piège

Mauvais : ?name=${nom}. Une ville avec une espace ou un & casse la requête.

Fix

Correct : encodeURIComponent(nom).

PERSONNALISER
  • Une icône par code météo : un objet qui associe chaque code à un petit SVG.
  • La position du visiteur avec navigator.geolocation, après lui avoir demandé la permission.
  • Les degrés Fahrenheit avec &temperature_unit=fahrenheit dans l'URL.
OPTIMISATION
  • Gardez la dernière réponse en mémoire dix minutes : la météo ne change pas à chaque clic.
  • Annulez la requête précédente avec AbortController si l'utilisateur relance une recherche.
VERS REACT

Trois états : chargement, données, erreur. Un useEffect lance la requête quand la ville change, et l'annule au nettoyage.

Pour plusieurs widgets qui lisent la même API, une bibliothèque de cache comme TanStack Query évite les requêtes en double.

Variantes
Commentaires
0/1000

Chargement des commentaires…