5. Les fonctions HTTP de TypeScript
Nous présentons ici deux façons de faire des requêtes HTTP en TypeScript : la fonction [fetch], native depuis Node 18, et la bibliothèque tierce [axios]. Les scripts de ce chapitre se trouvent dans le dossier [http] du projet.

5.1. Choix des outils HTTP
En 2019, fetch n'était pas encore implémentée par node.js, et le document original recommandait le package node-fetch. Depuis Node 18 (2022), [fetch] est une fonction globale native, standardisée par le WHATWG Fetch standard — plus besoin de l'importer.
[axios] reste néanmoins une bibliothèque intéressante : compatible aussi bien avec node.js qu'avec les navigateurs, elle offre une API un peu plus riche (intercepteurs, sérialisation JSON automatique, gestion d'erreurs uniformisée). Nous présentons les deux, avec le même exemple, pour montrer que la démarche de codage est analogue.
5.2. Le serveur de calcul de l'impôt
Ce chapitre, comme les suivants, fait référence au serveur NestJS installé précédemment. L’architecture de test est la suivante :
![]() |
En [A-B], un code Javascript exécuté par [node.js] va faire des requêtes [1] à l’application web [C]. Celle-ci lui enverra des réponses jSON (4). Le code Javascript du client peut être organisé en couches [UI, métier, dao] (UI : User Interface). C’est ce que nous ferons ultérieurement. Pour exécuter les scripts qui suivent, votre serveur NestJS doit être lancé.
5.3. script [fetch-01]
Ce script utilise [fetch] pour initialiser une session JSON avec le serveur de calcul d'impôt :
'use strict';
// [mise à jour 2026] en 2019, il fallait installer le package [node-fetch] pour disposer
// de la fonction [fetch] côté node. Depuis Node 18 (2022), [fetch] est une fonction
// globale native, standardisée par le "WHATWG Fetch standard" : plus besoin de l'importer.
// imports
import qs from 'qs';
import { sprintf } from 'sprintf-js';
import moment from 'moment';
// URL de base du serveur de calcul d'impôt
const baseUrl: string = 'http://localhost:3000/main.php?';
// init session
async function initSession(): Promise<any> {
// [mise à jour 2026] le [fetch] natif ne connaît pas l'option [timeout].
// pour limiter la durée d'attente, on lui fournit un [signal] produit par
// [AbortSignal.timeout(ms)] (disponible depuis Node 17.3) : passé ce délai,
// la requête est automatiquement annulée et [fetch] lève une erreur.
const options: RequestInit = {
method: "GET",
signal: AbortSignal.timeout(2000)
};
// exécution de la requête HTTP [get /main.php?action=init-session&type=json]
let débutFetch: moment.Moment | undefined;
try {
// requête asynchrone - [fetch] rend une promesse
débutFetch = moment(Date.now());
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// [response] est l'ensemble de la réponse HTTP du serveur (entêtes HTTP + réponse elle-même)
// on affiche cette réponse pour voir sa structure
console.log(sprintf("réponse fetch formatée en json,=%j, %s", response, heure(débutFetch)));
console.log("réponse fetch en javascript=", response);
// on peut avoir aux entêtes HTTP
console.log("entêtes de la réponse=", response.headers);
// si réponse de type application / json, la réponse json du serveur est obtenue avec la fonction asynchrone [response.json()]
// dans ce cas le code appelant obtient un objet [Promise]
// [await] permet d'obtenir la réponse [json] du serveur plutôt que sa promesse
const débutJson = moment(Date.now());
const objet = await response.json();
console.log(sprintf("réponse json=%j, type=%s, %s", objet, typeof (objet), heure(débutJson)));
return objet;
// si réponse de type text / plain, la réponse texte du serveur est obtenue avec [response.text()]
// dans ce cas le code appelant obtient un objet [Promise]
// [await] permet d'obtenir la réponse [texte] du serveur plutôt que sa promesse
// const text = await response.text();
// console.log("réponse texte=", text);
// return text;
} catch (error: any) {
// on est là parce que le serveur a envoyé un code d'erreur [404 Not Found, ...] accompagné d'un corps vide - on affiche l'erreur pour voir sa structure
// ou bien parce que le client [fetch] a lancé une exception (réseau inaccesible, ...)
// on affiche la structure de l'erreur
console.log(sprintf("error fetch en json=%j, %s", error, heure(débutFetch)));
console.log("error fetch en javascript=", typeof (error), error);
// on lance le msg d'erreur reçu
throw error.message;
}
}
// la fonction main exécute la fonction asynchrone [initSession]
async function main(): Promise<void> {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession();
console.log("succès ---------------------------------------------");
console.log("réponse=", response, typeof (response))
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error, typeof (error));
}
}
// test
main();
// utilitaire d'affichage heure et durée
function heure(début?: moment.Moment): string {
// heure du moment courant
const now = moment(Date.now());
// formatage heure
let result = "heure=" + now.format("HH:mm:ss:SSS");
// faut-il calculer une durée ?
if (début) {
const durée = now.valueOf() - début.valueOf();
const milliseconds = durée % 1000;
const seconds = Math.floor(durée / 1000);
// formatage heure + durée
result = result + sprintf(", durée= %s seconde(s) et %s millisecondes", seconds, milliseconds);
}
// résultat
return result;
}
- lignes 3-5 : [mise à jour 2026] — commentaire signalant que fetch est désormais natif, contrairement à 2019 ;
- ligne 13 : cette ligne est importante. Elle indique l’entête des URL que le script va interroger. Celui-ci sera complété par d’éventuels paramètres. Ici nous avons utilisé la configuration définie au paragraphe Installation d’un serveur NestJS ;
- ligne 22 : AbortSignal.timeout(2000) — remplace l'option timeout de node-fetch (qui n'existe pas sur fetch natif) : au-delà de 2 secondes, la requête est automatiquement annulée ;
- ligne 29 : fetch(URL, options) — la syntaxe reste celle du fetch standard : une URL, et un objet d'options (méthode, signal d'annulation...) ;
- lignes 30-31 : on initie une session jSON ;
- ligne 36 : on affiche l’intégralité de la réponse du serveur ;
- ligne 38 : on affiche l’entête de la réponse appelé “headers” ;
- ligne 43 : await response.json() — extrait le corps JSON de la réponse ; c'est une opération elle-même asynchrone (response peut être un flux en cours de réception) ;
- ligne 52 : fetch ne lance une exception que si la requête HTTP n'a pu aboutir (réseau inaccessible, timeout...). Si une réponse est reçue, même avec un code d'erreur (400, 500...), fetch ne lance pas d'exception : la réponse est disponible normalement, ligne 38.
Résultat de l'exécution :
requête HTTP vers le serveur en cours ---------------------------------------------
réponse fetch formatée en json,={}, heure=12:36:31:319, durée= 0 seconde(s) et 93 millisecondes
réponse fetch en javascript= Response {
status: 200,
statusText: 'OK',
headers: Headers {
date: 'Sun, 06 Sep 2026 10:36:31 GMT',
server: 'Apache/2.4.66 (Win64) OpenSSL/3.0.18 PHP/8.3.30',
'x-powered-by': 'PHP/8.3.30',
'cache-control': 'max-age=0, private, must-revalidate, no-cache, private',
'set-cookie': 'PHPSESSID=9u1rb9euj0m6f18efm7b5m952t; path=/',
'content-length': '86',
connection: 'close',
'content-type': 'application/json'
},
body: ReadableStream { locked: false, state: 'readable', supportsBYOB: true },
bodyUsed: false,
ok: true,
redirected: false,
type: 'basic',
url: 'http://localhost/main.php?action=init-session&type=json'
}
entêtes de la réponse= Headers {
date: 'Sun, 06 Sep 2026 10:36:31 GMT',
server: 'Apache/2.4.66 (Win64) OpenSSL/3.0.18 PHP/8.3.30',
'x-powered-by': 'PHP/8.3.30',
'cache-control': 'max-age=0, private, must-revalidate, no-cache, private',
'set-cookie': 'PHPSESSID=9u1rb9euj0m6f18efm7b5m952t; path=/',
'content-length': '86',
connection: 'close',
'content-type': 'application/json'
}
réponse json={"action":"init-session","état":700,"réponse":"session démarrée avec type [json]"}, type=object, heure=12:36:31:323, durée= 0 seconde(s) et 2 millisecondes
succès ---------------------------------------------
réponse= {
action: 'init-session',
'état': 700,
'réponse': 'session démarrée avec type [json]'
} object
- lignes 3-22 : la totalité de la réponse du serveur ;
- ligne 4 : le code 200 signifie que le serveur a pu traiter l’URL demandée. Celle-ci est indiquée à la ligne 21. Nous avons déjà utilisé cette URL avec le client Postman ;
- lignes 23-32 : l’entête (headers) de la réponse. Il donne des informations sur la réponse qui va suivre. Ainsi ligne 29, le serveur indique que cette réponse a 86 caractères ;
- ligne 28 : le serveur a envoyé un cookie de session. Celui-ci permet à un client de maintenir sur le serveur une mémoire appelée session. Celle-ci est gérée par le serveur web. Après avoir reçu ce cookie de session, qui est en fait son identifiant auprès du serveur, le client doit le renvoyer à chaque nouvelle requête. Notez la forme de ce cookie de session. Nous allons prochainement le récupérer dans un client TypeScript.
- ligne 33 : la réponse jSON du serveur ;
5.4. script [fetch-02]
Ce script reprend fetch-01 en le débarrassant de tous les détails de démonstration inutiles à l'usage courant :
'use strict';
// [mise à jour 2026] [fetch] est désormais une fonction globale native de node
// (depuis Node 18) : plus besoin d'importer le package [node-fetch] comme en 2019.
// imports
import qs from 'qs';
// URL de base du serveur de calcul d'impôt
const baseUrl: string = 'http://localhost:3000/main.php?';
// init session
async function initSession(): Promise<any> {
// options de la requête HHTP [get /main.php?action=init-session&type=json]
// [AbortSignal.timeout(ms)] remplace l'option [timeout] qui n'existe pas sur fetch natif
const options: RequestInit = {
method: "GET",
signal: AbortSignal.timeout(2000)
};
// exécution de la requête HTTP [get /main.php?action=init-session&type=json]
const response = await fetch(baseUrl + qs.stringify({
action: 'init-session',
type: 'json'
}), options);
// résultat reçu en jSON
return await response.json();
}
// la fonction main exécute la fonction asynchrone [initSession]
async function main(): Promise<void> {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession();
console.log("succès ---------------------------------------------");
console.log("réponse=", response)
} catch (error: any) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error.message);
}
}
// test
main();
Résultat de l'exécution :
5.5. script [axios-01]
Même exemple, avec [axios] :
'use strict';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
// configuration par défaut d'axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost:3000/';
// init session
async function initSession(axios: AxiosInstance): Promise<any> {
// options de la requête HHTP [get /main.php?action=init-session&type=json]
const options: AxiosRequestConfig = {
// [mise à jour TypeScript] axios.request() n'accepte, côté typage, qu'un seul
// argument de configuration : l'URL doit donc figurer dans [options.url]
// plutôt qu'en 1er paramètre séparé de request()
url: 'main.php',
method: "GET",
// paramètres de l'URL
params: {
action: 'init-session',
type: 'x'
}
};
// exécution de la requête HTTP [get /main.php?action=init-session&type=json]
try {
// requête asynchrone
const response = await axios.request(options);
// response est l'ensemble de la réponse HTTP du serveur (entêtes HTTP + réponse elle-même)
// on affiche cette réponse pour voir sa structure
// console.log("réponse axios=", response);
// la réponse du serveur est dans [response.data]
return response.data;
} catch (error: any) {
// on est là parce que le serveur a envoyé un code d'erreur [404 Not Found, 500 Internal Server Error, ...]
// le paramètre [error] est une instance d'exception - elle peut avoir diverses formes
// on l'affiche pour voir sa structure
// console.log("axios error=", typeof (error), error);
if (error.response) {
// le serveur a signalé une erreur dans le statut HTTP mais il a aussi envoyé une réponse
// alors celle-ci est trouvée dans [error.response.data]
// on sait que le serveur envoie des réponses jSON de structure {action, état, réponse}
// et qu'en cas d'erreur, le msg d'erreur est dans [réponse]
return error.response.data;
} else {
// on lance l'erreur
throw error;
}
}
}
// la fonction main exécute la fonction asynchrone [initSession]
async function main(): Promise<void> {
try {
console.log("requête HTTP vers le serveur en cours ---------------------------------------------");
const response = await initSession(axios);
console.log("succès ---------------------------------------------");
console.log("réponse=", response, typeof (response))
} catch (error: any) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error.message);
}
}
// test
main();
- l’URL interrogée est construite à partir des informations des lignes 6, 16, 19 et 20 ;
- ligne 26 : axios.request(options) — contrairement à fetch, l'URL et les options sont regroupées dans un seul objet de configuration (ligne 11) ;
- ligne 37 : error.response — si le serveur a répondu (même avec un code d'erreur), axios place cette réponse dans error.response, accessible dans le catch — contrairement à fetch, axios lance systématiquement une exception dès que le code HTTP n'est pas un succès (2xx) ;
- ligne 31 : la réponse réussie est dans response.data — axios fait automatiquement l'extraction JSON, pas besoin d'un await response.json() séparé comme avec fetch.
Résultat de l'exécution :
5.6. script [axios-03] — authentification
Ce script enchaîne deux requêtes : init-session, puis authentifier-utilisateur en [POST], avec un corps encodé par la bibliothèque [qs] :
'use strict';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import qs from 'qs'
// configuration axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost:3000/';
// init session
async function initSession(axios: AxiosInstance): Promise<any> {
// options de la requête HHTP [get /main.php?action=init-session&type=json]
const options: AxiosRequestConfig = {
// [mise à jour TypeScript] URL incluse dans [options.url] (axios.request() typé n'accepte qu'un seul argument)
url: 'main.php',
method: "GET",
// paramètres de l'URL
params: {
action: 'init-session',
type: 'json'
}
};
try {
// exécution de la requête HTTP [get /main.php?action=init-session&type=json]
const response = await axios.request(options);
// la réponse du serveur est dans [response.data]
return response.data;
} catch (error: any) {
// réponse du serveur
if (error.response) {
// la réponse jSON est dans [error.response.data]
return error.response.data;
} else {
// on relance l'erreur
throw error;
}
}
}
async function authentifierUtilisateur(axios: AxiosInstance, user: string, password: string): Promise<any> {
// options de la requête HHTP [post /main.php?action=authentifier-utilisateur]
const options: AxiosRequestConfig = {
// [mise à jour TypeScript] URL incluse dans [options.url]
url: 'main.php',
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// corps du POST
data: qs.stringify({
user: user,
password: password
}),
// paramètres de l'URL
params: {
action: 'authentifier-utilisateur'
}
};
try {
// exécution de la requête HTTP [post /main.php?action=authentifier-utilisateur]
const response = await axios.request(options);
// la réponse du serveur est dans [response.data]
return response.data;
} catch (error: any) {
// réponse du serveur
if (error.response) {
// la réponse jSON est dans [error.response.data]
return error.response.data;
} else {
// on relance l'erreur
throw error;
}
}
}
// la fonction main exécute les fonctions asynchrones une par une
async function main(): Promise<void> {
try {
// init-session
console.log("action init-session en cours ---------------------------------------------");
const response1 = await initSession(axios);
console.log("succès ---------------------------------------------");
console.log("réponse=", response1);
// authentifier-utilisateur
console.log("action authentifier-utilisateur en cours ---------------------------------------------");
const response2 = await authentifierUtilisateur(axios, 'admin', 'admin');
console.log("succès ---------------------------------------------");
console.log("réponse=", response2)
} catch (error) {
console.log("erreur ---------------------------------------------");
console.log("erreur=", error);
}
}
// test
main();
- lignes 42-53 : la requête POST envoie ses paramètres (user, password) encodés en application/x-www-form-urlencoded, via qs.stringify(...) dans options.data ;
- lignes 55-57 : l’URL [post /main.php?action=authentifier-utilisateur] a également un paramètre dans l’URL ;
- les deux fonctions sont exécutées séquentiellement dans main (await l'une après l'autre) (lignes 81, 86) : la seconde ne peut avoir de sens que si la première a réussi, puisqu'elle dépend du cookie de session établi par init-session.
Résultat de l'exécution :
action init-session en cours -----------------------
succès ---------------------------------------------
réponse= {
action: 'init-session',
'état': 700,
'réponse': 'session démarrée avec type [json]'
}
action authentifier-utilisateur en cours ----------------------
succès ---------------------------------------------
réponse= {
action: 'authentifier-utilisateur',
'état': 103,
'réponse': [ 'pas de session en cours. Commencer par action [init-session]' ]
}
- lignes 10-14 : l’action [authentifier-utilisateur] a échoué. La raison en est la suivante :
- l’action [init-session] n’a pas envoyé au serveur de cookie de session. C’est son identifiant auprès du serveur. Parce qu’il n’a pas envoyé cet identifiant, le client est inconnu du serveur. Dans sa réponse, celui-ci a inclus un cookie de session. Cela veut dire au client : “Voici ton identifiant pour tes prochaines requêtes” ;
- mais l’action [authentifier-utilisateur] n’a pas, elle non plus, envoyé au serveur le cookie de session. Ceci parce que [init-session] n’a pris le soin de le mémoriser. Le serveur ne reconnaît pas alors le client et ne sait pas qu’il a initié précédemment une session jSON et il le lui dit ;
La solution à ce problème est de gérer le cookie de session envoyé par le serveur :
- la toute première requête faite au serveur, doit mémoriser le cookie de session envoyé par le serveur ;
- les requêtes suivantes doivent récupérer ce cookie de session et l’envoyer au serveur pour s’identifier ;
5.7. script [axios-04] — gestion du cookie de session
Le code reprend le précédent mais ajoute une fonction [getRemoteData] pour gérer le cookie de session :
'use strict';
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import qs from 'qs'
// configuration axios
axios.defaults.timeout = 2000;
axios.defaults.baseURL = 'http://localhost:3000/';
// cookie de session
const sessionCookieName: string = "connect.sid";
let sessionCookie: string = '';
// init session
async function initSession(axios: AxiosInstance): Promise<any> {
// options de la requête HHTP [get /main.php?action=init-session&type=json]
const options: AxiosRequestConfig = {
// [mise à jour TypeScript] URL incluse dans [options.url]
url: 'main.php',
method: "GET",
// paramètres de l'URL
params: {
action: 'init-session',
type: 'json'
}
};
// exécution de la requête HTTP
return await getRemoteData(axios, options);
}
async function authentifierUtilisateur(axios: AxiosInstance, user: string, password: string): Promise<any> {
// options de la requête HHTP [post /main.php?action=authentifier-utilisateur]
const options: AxiosRequestConfig = {
// [mise à jour TypeScript] URL incluse dans [options.url]
url: 'main.php',
method: "POST",
headers: {
'Content-type': 'application/x-www-form-urlencoded',
},
// corps du POST
data: qs.stringify({
user: user,
password: password
}),
// paramètres de l'URL
params: {
action: 'authentifier-utilisateur'
}
};
// exécution de la requête HTTP
return await getRemoteData(axios, options);
}
async function getRemoteData(axios: AxiosInstance, options: AxiosRequestConfig): Promise<any> {
// pour le cookie de session
if (!options.headers) {
options.headers = {} as any;
}
(options.headers as any).Cookie = sessionCookie;
// exécution de la requête HTTP
let response: AxiosResponse;
try {
// requête asynchrone
response = await axios.request(options);
} catch (error: any) {
// le paramètre [error] est une instance d'exception - elle peut avoir diverses formes
if (error.response) {
// la réponse du serveur est dans [error.response]
response = error.response;
} else {
// on relance l'erreur
throw error;
}
}
// response est l'ensemble de la réponse HTTP du serveur (entêtes HTTP + réponse elle-même)
// on récupère le cookie de session s'il existe
const setCookie = response.headers['set-cookie'];
if (setCookie) {
// setCookie est un tableau
// on cherche le cookie de session dans ce tableau
let trouvé = false;
let i = 0;
while (!trouvé && i < setCookie.length) {
// on cherche le cookie de session
const results = RegExp('^(' + sessionCookieName + '.+?);').exec(setCookie[i]);
if (results) {
// on mémorise le cookie de session
// eslint-disable-next-line require-atomic-updates
sessionCookie = results[1];
// on a trouvé
trouvé = true;
} else {
// élément suivant
i++;
}
}
}
// la réponse du serveur est dans [response.data]
return response.data;
}
// la fonction main exécute les fonctions asynchrones une par une
async function main(): Promise<void> {
try {
// init-session
console.log("action init-session en cours ----------------");
const response1 = await initSession(axios);
console.log("succès --------------------------");
console.log("réponse=", response1);
// authentifier-utilisateur
console.log("action authentifier-utilisateur en cours ---------");
const response2 = await authentifierUtilisateur(axios, 'admin', 'admin');
console.log("succès -------------------");
console.log("réponse=", response2)
} catch (error: any) {
console.log("erreur ------------------");
console.log("erreur=", error.message);
}
}
// test
main();
Ce script factorise initSession et authentifierUtilisateur autour d'une fonction commune [getRemoteData], qui gère explicitement le cookie de session PHP (PHPSESSID) — indispensable puisque le serveur associe l'authentification et les simulations à une session HTTP :
- ligne 10 : le nom du cookie de session recherché. Il dépend du serveur Web utilisé. Le serveur NestJS utilisé dans ce cours utilise un cookie de session qui a pour nom [connect.sid] ;
- ligne 53 : la fonction [getRemoteData] gère l’envoi des requêtes et la réception de la réponse du serveur. De plus, elle gère le cookie de session. Elle reçoit deux paramètres :
- l’objet [AxiosInstance] qui gère la mécanique générale des requêtes HTTP Axios. Cet objet et d’autres sont obtenus par l’import de la ligne 2 ;
- l’objet [AxiosRequestConfig] qui définit les options d’une requête en particulier ;
- lignes 54-58 : [options.headers] fixe l’entête de la requête HTTP qui va être envoyée au serveur. Si un cookie de session existe, on doit le mettre dans cet entête. C’est la ligne 58 qui fait cela. A l’issue de la première requête [getRemoteData] va mémoriser ce cookie dans la variable globale définie ligne 11. Lors de la première requête, sa valeur sera la chaîne vide. Pour les requêtes suivantes, ce sera la chaîne de caractères du cookie de session envoyé par le serveur en réponse à la première requête.
- ligne 63 : la requête HTTP est exécutée ;
- ligne 76 : on regarde dans l’entête de la réponse, s’il y a une ligne ‘set-cookie’. Cette ligne n’est présente que si la requête précédente du client n’a pas envoyé la ligne ‘Cookie’ dans ses entêtes. Lorsque le serveur reçoit du client une requête HTTP avec la ligne ‘Cookie’, il ne renvoie plus le cookie de session car il sait que le client l’a. C’est au client de le renvoyer à chaque nouvelle requête. C’est ce qui est fait ligne 58 ;
- ligne 77 : si le serveur a envoyé l’entête [Set-Cookie] alors il faut récupérer ce contenu. Cet entête peut englober plusieurs cookies sous la forme [nom_cookie=valeur]. Les lignes 77-95 ne seront exécutées qu’une fois au cours de l’exécution de script. On l’a dit, le serveur n’envoie pas le cookie de session en réponse aux requêtes qui se sont authentifiées avec ce même cookie de session ;
- ligne 84 : on cherche explicitement le cookie dont le nom a été mémorisé ligne 10 ;
- ligne 88 : si on le trouve, on le mémorise dans la variable globale de la ligne 11 ;
Ce mécanisme fait que :
- le cookie de session est récupéré dans la réponse à la première requête HTTP ;
- il est envoyé ensuite systématiquement au serveur à chaque nouvelle requête, ce qui permet au serveur de reconnaître son client ;
On exécute le code :
Résultat de l'exécution :
action init-session en cours -----------------------
succès ---------------------------------------------
réponse= {
action: 'init-session',
'état': 700,
'réponse': 'session démarrée avec type [json]'
}
action authentifier-utilisateur en cours ----------------------
succès ---------------------------------------------
réponse= {
action: 'authentifier-utilisateur',
'état': 200,
'réponse': 'Authentification réussie [admin, admin]'
}
5.8. script [fetch-03] — annulation de requêtes
[NOUVEAU depuis 2019] Ce script illustre deux usages du mécanisme d'annulation des requêtes fetch, disponible nativement depuis Node 18 :
'use strict';
// ========================================================================
// [NOUVEAU depuis 2019] fetch natif + annulation d'une requête HTTP
// ========================================================================
// [fetch] est global depuis Node 18 : plus besoin du package [node-fetch]
// utilisé en 2019 dans fetch-01.js/fetch-02.js (voir les commentaires [mise à jour 2026]
// ajoutés dans ces deux fichiers)
// URL de base du serveur de calcul d'impôt (voir http/README.md)
// comme pour axios-01.js, ce script suppose que le serveur PHP du cours tourne
// en local : sans lui, les requêtes échouent avec "fetch failed", ce qui est normal
const baseUrl: string = 'http://localhost:3000/main.php';
// exemple 1 : requête avec délai maximum grâce à AbortSignal.timeout()
async function requêteAvecDélaiMaximum(): Promise<void> {
console.log("--- requête avec AbortSignal.timeout ---");
try {
const response = await fetch(baseUrl + '?action=init-session&type=json', {
// au-delà de 2 secondes, la requête est annulée automatiquement
signal: AbortSignal.timeout(2000)
});
const données = await response.json();
console.log("réponse =", données);
} catch (erreur: any) {
// si le délai est dépassé,
// [erreur.name] vaut "TimeoutError" ou "AbortError" selon le cas
console.log("erreur.name =", erreur.name, ", message =", erreur.message);
}
}
// exemple 2 : annulation manuelle d'une requête, par exemple parce que
// l'utilisateur a changé d'avis (ex : il retape dans un champ de recherche)
async function requêteAnnulableManuellement(): Promise<void> {
console.log("--- requête annulée manuellement ---");
const contrôleur = new AbortController();
// on programme une annulation "métier" au bout de 500 ms
// (dans une vraie application, ce serait par exemple un clic sur un bouton "annuler")
setTimeout(() => {
console.log("annulation manuelle déclenchée");
contrôleur.abort();
}, 10);
try {
const response = await fetch(baseUrl + '?action=init-session&type=json', {
signal: contrôleur.signal
});
const données = await response.json();
console.log("réponse =", données);
} catch (erreur: any) {
console.log("erreur.name =", erreur.name, ", message =", erreur.message);
}
}
async function main(): Promise<void> {
await requêteAvecDélaiMaximum();
await requêteAnnulableManuellement();
}
main();
- [AbortSignal.timeout(ms)] : annule automatiquement la requête si elle dépasse le délai donné — pattern déjà vu au script fetch-01 ;
- [AbortController] : permet une annulation manuelle, déclenchée par n'importe quel événement applicatif (ici un setTimeout simulant, par exemple, un clic sur un bouton « Annuler », ou une nouvelle frappe dans un champ de recherche qui invalide la requête précédente).
Résultat de l'exécution :
- lignes 2-6 : la première requête s’est terminée normalement ;
- lignes 8-9 : la seconde requête a été annulée à cause du délai très court (10 ms) donné à la requête (ligne 43 du code) ;
