Séance 7

Applications complètes

Rémi Sharrock

TypeScript 101, Télécom Paris

Échauffement

Deux questions sur la séance 6, tirées des QCM du cours.

Question 1 (chapitre 6.1)

Qu’affiche ce code ? attendre(ms) renvoie une promesse tenue après ms millisecondes.

async function charger(): Promise<void> {
  console.log("1");
  await attendre(1000);
  console.log("2");
}

charger();
console.log("3");
  • A. 1 2 3 · B. 1 3 2 · C. 3 1 2 · D. 3 2 1

B. Au premier await, la fonction rend la main.

Question 2 (chapitre 6.2)

Le serveur répond 404 Not Found. Que se passe-t-il ?

const response = await fetch(url);
  • A. La promesse est rompue : il faut un catch
  • B. La promesse est tenue, et response.ok vaut false
  • C. response vaut null
  • D. response.status vaut 0

B. Testez toujours response.ok. C’est ce que fera chaque client CRUD de la séance.

Objectifs

  • Associer chaque opération CRUD à son verbe HTTP
  • Tester une API avec json-server
  • Intercepter un submit, lire et typer les champs d’un formulaire

Mini-cours court : la séance l’est aussi. L’essentiel se passe dans les exercices.

HTTP et CRUD

CRUD et verbes

Opération Verbe URL type Corps Statut
Create POST /restaurants oui 201 Created
Read GET /restaurants/12b3 non 200 OK
Update PUT / PATCH /restaurants/12b3 oui 200 OK
Delete DELETE /restaurants/12b3 non 200 ou 204

/restaurants désigne la collection, /restaurants/12b3 désigne un élément. On crée dans une collection ; on modifie ou supprime un élément.

Les codes de statut

Code Nom Sens pratique
200 OK la réponse contient le résultat
201 Created créé, URL dans l’en-tête Location
204 No Content réussi, rien à renvoyer
400 Bad Request requête mal formée
401 Unauthorized non identifié
403 Forbidden identifié, mais pas le droit
404 Not Found la ressource n’existe pas
500 Server Error le serveur a planté

2xx succès · 4xx votre faute · 5xx la sienne.

Le serveur de test : json-server

Il transforme un fichier JSON en API REST complète.

npm install json-server
npx json-server db.json
curl http://localhost:3000/restaurants

Chaque clé de premier niveau devient une route : /restaurants, /categories.

db.json est modifié pour de bon

Un POST, PATCH ou DELETE réécrit le fichier sur le disque. Au deuxième lancement, le DELETE renverra 404 et le POST créera un doublon.

Gardez une copie de db.json de côté.

Formulaires

submit et preventDefault

handleSubmit(event: Event) {
  event.preventDefault();   // sans cette ligne, la page se recharge
  const name = this.nameInput.value;

  if (name.length < 4) {
    this.result.style.color = "red";
    this.result.textContent = "Name must be at least 4 characters long.";
  } else {
    this.result.style.color = "green";
    this.result.textContent = `Name Ok: ${name}`;
  }
}

Écoutez submit sur le formulaire, jamais click sur le bouton : la touche Entrée dans un champ soumet aussi.

Récupérer et typer

getElementById retourne HTMLElement | null, qui n’a ni .value ni .checked.

// Assertion : « fais-moi confiance »
const nameInput = document.getElementById("name") as HTMLInputElement;

// Vérification : le compilateur restreint le type tout seul
const el = document.getElementById("name");
if (el instanceof HTMLInputElement) {
  console.log(el.value);
}

La seconde est plus sûre : si l’id a été renommé, la première plante avec Cannot read properties of null.

Pourquoi .bind(this) ?

Quand le navigateur déclenche l’événement, il appelle la fonction en fixant this sur l’élément qui porte l’écouteur : ici le <form>.

Votre méthode chercherait donc this.nameInput sur un formulaire, où cette propriété n’existe pas : undefined, puis Cannot read properties of undefined.

this.myForm.addEventListener("submit", this.handleSubmit.bind(this));
this.myForm.addEventListener("submit", (e) => this.handleSubmit(e));

Les deux écritures marchent : une fonction fléchée ne crée pas son propre this.

Après la séance

En autonomie : le composant minimal

Le chapitre 7.3 Web components se fait après la séance. Seul le composant minimal est au programme de l’évaluation 2 :

class MonElement extends HTMLElement {
  static get observedAttributes(): string[] { return ["mon-attribut"]; }
  connectedCallback(): void { this.render(); }
  attributeChangedCallback(): void { this.render(); }
  render(): void { this.textContent = this.getAttribute("mon-attribut") ?? ""; }
}
customElements.define("mon-element", MonElement);

Préparer l’évaluation 2

La page Préparer l’évaluation 2 du site propose un plan en cinq étapes :

  1. finir les exercices « essentiel » de cette séance et le composant minimal ;
  2. refaire sans corrigé la POO et les tableaux ;
  3. puis JSON, generics, exceptions ;
  4. puis async, fetch, CORS, et une annale en conditions réelles ;
  5. une seconde annale, les « À retenir », l’outillage d’examen.

Une grille d’auto-évaluation, compétence par compétence, termine la page.

À vous : par où commencer

Parcours essentiel, en séance

  • 7.1 Explorer l’API à la main
  • 7.2 Lire et chercher
  • 7.3 Rendre les erreurs visibles
  • 7.5 Reproduire et casser
  • 7.6 Ajouter un restaurant (transfert)
  • 7.7 Inscription complète

Après la séance

  • 7.9 <date-time>
  • 7.10 <greet-custom> (transfert)

Ensuite

  • 7.4 Maintenir les relations (approfondissement, transfert)
  • 7.8 Formulaire et API, la qualité de l’air (approfondissement)
  • 7.11 Encapsuler le style (approfondissement)

Ce qui n’est pas fini en séance se termine en autonomie, avec la page « Préparer l’évaluation 2 ».