N.S.I. WorkSpace T-Th-D,Terminale D.3 – Modularité

D.3 – Modularité

Categories:

Pour aller plus loin…

Utiliser un service via une API, avec Javascript

Considérons le service proposé par la NASA de consultation des photos prises par les missions sur Mars.

Dans la barre d’URL d’un navigateur, saisir :
https://api.nasa.gov/mars-photos/api/v1/manifests/curiosity?api_key=DEMO_KEY

Attention ! Remplacer DEMO_KEY par une clé (jeton) valide.

Lorsque l’on valide, le navigateur envoie une requête HTTP à l’API située au niveau d’un serveur Web.
Ce dernier envoie une réponse HTTP au client qui contient des données formatées. Celles-ci s’affichent dans la fenêtre du navigateur. En voici un extrait :

{"photo_manifest":{"name":"Curiosity","landing_date":"2012-08-06","launch_date":"2011-11-26","status":"active","max_sol":3729,"max_date":"2023-02-01","total_photos":627873,"photos":[{"sol":0,"earth_date":"2012-08-06","total_photos":3702,"cameras":["CHEMCAM","FHAZ","MARDI","RHAZ"]},
...,
{"sol":3729,"earth_date":"2023-02-01","total_photos":39,"cameras":["CHEMCAM","NAVCAM"]}]}}

Ces informations correspondent au manifeste des photos prises par une mission, ici de la mission ‘curiosity’.

Il s’agit maintenant de voir comment envoyer la même requête http à partir d’un script écrit en javascript, de récupérer la réponse http, puis d’en exploiter le contenu.

Pour atteindre cet objectif il faut envisager l’utilisation d’une classe appelée : XMLHttpRequest

Consulter

Documentation complète de cette classe, disponible en ligne (en anglais)

Etape 1 – Instanciation de la classe (appel du constructeur)

var req_http = new XMLHttpRequest();

Etape 2 – Initialisation de la requête (appel de la méthode open())

// apiMET : STR, méthode utilisée pour la soumission de la requête, valeur : GET ou POST
// apiURL : STR, url de l'API + ? + paramètres (clé=valeur&...)
req_http.open(apiMET, apiURL, true);

Etape 3 – Envoi de la requête (appel de la méthode send())

req_http.send();

Etape 4 – Attente d’un changement d’état (écoute de l’événement onreadystatechange)
Dès que la valeur de l’attribut readyState change, on exécute le bloc d’instructions contenu dans une fonction.

req_http.onreadystatechange = function(){
  // bloc d'instructions
}

Etape 5 – Tests des valeurs des attributs ‘readyState’ et ‘status‘, et le cas échéant lecture puis affichage du contenu du corps de la réponse.
Le mot ‘this’ est l’équivalent du mot ‘self’ utilisé en Python.
Les caractères « && » correspond à l’opérateur booléen « AND ».

if(this.readyState == 4 && this.status == 200){
  ...
}

Le contenu du corps de la réponse a été affecté à l’attribut ‘responseText

// Tests des valeurs des attributs 'readyState' et 'status'
// le mot 'this' est l'équivalent du mot 'self' utilisé en Python.
if(this.readyState == 4 && this.status == 200){
	// Le contenu du corps de la réponse a été affecté à l'attribut 'responseText'
	// Affichage du contenu du corps de la réponse dans un élément HTML
	document.getElementById("manifeste").innerHTML = req_http.responseText;
}

Ouvrir un EDI (Environnement de développement Intégré) comme Geany.
Copier le code contenu dans le bloc qui suit, le coller dans l’EDI, et enfin sauvegarder sous la forme d’un fichier avec extension ‘.html’
Ouvrir un navigateur : activer les outils de développement (Ctrl + Maj + I) et ouvrir l’onglet « Réseau ».
Rechercher dans l’arborescence le fichier html sauvegardé : ouvrir le menu contextuel, sélectionner ‘Ouvrir avec… » et choisir le navigateur qui vient d’être ouvert.

<!DOCTYPE html>
<html lang="fr">
	<!--
	   Lycée - Terminale - Spécialité NSI
	   D - Programmation
	   API

	   Nasa API : https://api.nasa.gov/
	   Mars Rover Photos

	-->

	<head>
		<meta charset="utf-8" />
		<title>API - Nasa - Mars Rover Photos</title>
	</head>

	<body>
		
		<p>Manifeste de la mission</p>
		<p id="manifeste"></p>

	</body>
	
	<script>
        // -----------------------------------------------------------------------
		// Construction d'une chaîne de caractères correspondant à la requête http
		// -----------------------------------------------------------------------
		var apiMet = "GET";  // Méthode de soumission de la requête
		var apiKey = "RBRY9REFVaQ3EBwH7zyq3dx4lSVOFVhazhNunAzi"; // Saisir une clé valide
		var apiUrl = "https://api.nasa.gov/mars-photos/api/v1/manifests/";
		var apiMis = "curiosity";
		var apiReq = apiUrl + apiMis + "?api_key=" + apiKey;
		
		// -----------------------------------------------------------------------
		// Utilisation de la classe XMLHttpRequest
		// -----------------------------------------------------------------------
		
		// Instanciation
		var req_http = new XMLHttpRequest();
		
		console.log(req_http.readyState);
		
		// Initialisation de la requête HTTP
		req_http.open(apiMet, apiReq, true);
		
		console.log(req_http.readyState);
		
		// Soumission de la requête HTTP
		req_http.send();
		
		console.log(req_http.readyState);
		
		// Attente du changement de valeur de l'attribut readyState
		req_http.onreadystatechange = function(){
			
			console.log(req_http.readyState);
			
			// Tests des valeurs des attributs 'readyState' et 'status'
			// le mot 'this' est l'équivalent du mot 'self' utilisé en Python.
			if(this.readyState == 4 && this.status == 200){

				// Affichage du contenu du coprs de la réponse dans un élément HTML
				document.getElementById("manifeste").innerHTML =req_http.responseText;
			}
		}
	</script>

</html>

Lorsqu’on ouvre cette page dans un client web (= navigateur), on voit s’afficher un très long texte, dont voici un aperçu.

{"photo_manifest":{"name":"Curiosity","landing_date":"2012-08-06","launch_date":"2011-11-26","status":"active","max_sol":3725,"max_date":"2023-01-28","total_photos":626833,"photos":[{"sol":0,"earth_date":"2012-08-06","total_photos":3702,"cameras":["CHEMCAM","FHAZ","MARDI","RHAZ"]},{"sol":1,"earth_date":"2012-08-07","total_photos":16,"cameras":["MAHLI","MAST","NAVCAM"]},{"sol":2,"earth_date":"2012-08-08","total_photos":74,"cameras":["NAVCAM"]},{"sol":3,"earth_date":"2012-08-09","total_photos":338,"cameras":["MAST"]},{"sol":10,"earth_date":"2012-08-16","total_photos":26,"cameras":["CHEMCAM","MAHLI","NAVCAM"]},{"sol":12,"earth_date":"2012-08-18","total_photos":32,"cameras":["CHEMCAM","NAVCAM"]},{"sol":13,"earth_date":"2012-08-19","total_photos":208,"cameras":["CHEMCAM","MAST","NAVCAM"]},{"sol":14,"earth_date":"2012-08-20","total_photos":70,"cameras":["CHEMCAM","FHAZ","MAST","NAVCAM"]},{"sol":15,"earth_date":"2012-08-21","total_photos":58,"cameras":["CHEMCAM","FHAZ","NAVCAM","RHAZ"]},{"sol":16,"earth_date":"2012-08-22","total_photos":78,"cameras":["FHAZ","NAVCAM","RHAZ"]},{"sol":17,"earth_date":"2012-08-23","total_photos":273,"cameras":["MAST","NAVCAM"]},{"sol":19,"earth_date":"2012-08-25","total_photos":444,"cameras":["CHEMCAM","MAST"]},{"sol":20,"earth_date":"2012-08-26","total_photos":1046,"cameras":["MAST"]},{"sol":21,"earth_date":"2012-08-27","total_photos":73,"cameras":["FHAZ","MARDI","MAST","NAVCAM","RHAZ"]},{"sol":22,"earth_date":"2012-08-28","total_photos":52,"cameras":["CHEMCAM","FHAZ","NAVCAM","RHAZ"]},{"sol":23,"earth_date":"2012-08-29","total_photos":379,"cameras":["MARDI","MAST","NAVCAM"]},

Il est possible de convertir cette chaîne de caractères en objet avec la méthode JSON.parse() de javascript.

On remplace donc la ligne 36 du code précédente par celle-ci :

manMis = JSON.parse(xhttp.responseText);

Dès lors l’objet manMis « s’utilise » comme un dictionnaire en Python, comme en témoigne la capture d’écran suivante de la console Javascript :

Nous pouvons donc modifier le code de la page Web pour afficher les données de cet Objet.

<!DOCTYPE html>
<html lang="fr">
	<!--
	   Lycée - Terminale - Spécialité NSI
	   D - Programmation
	   API

	   Nasa API : https://api.nasa.gov/
	   Mars Rover Photos

	-->

	<head>
		<meta charset="utf-8" />
		<title>API - Nasa - Mars Rover Photos</title>
	</head>

	<body>
		
		<p>Manifeste de la mission</p>
		<p id="manifeste"></p>
		<p id="mission"></p>

	</body>
	
	<script>
		
		var apiMet = "GET";
		var apiKey = "RBRY9REFVaQ3EBwH7zyq3dx4lSVOFVhazhNunAzi";
		var apiUrl = "https://api.nasa.gov/mars-photos/api/v1/manifests/";
		var apiMis = "curiosity";
		var apiReq = apiUrl + apiMis + "?api_key=" + apiKey;
		
		var xhttp = new XMLHttpRequest();
			
		xhttp.onreadystatechange = function(){
			if(this.readyState == 4 && this.status == 200){
				manMis = JSON.parse(xhttp.responseText);
				manifeste = "";
				manMis = manMis["photo_manifest"];
				document.getElementById("mission").innerHTML = manifeste;
				manifeste += "Nom de la mission : " + manMis["name"] + "<br>";
				manifeste += "Date d'amarsissage : " + manMis["landing_date"] + "<br>";
				manifeste += "Date de lancement : " + manMis["launch_date"] + "<br>";
				manifeste += "Statut : " + manMis["status"] + "<br>";
				manifeste += "Date des dernières photos prises - en nombre de jours solaires martiens depuis le jour d'amarsissage (0) : " + manMis["max_sol"] + "<br>";
				manifeste += "Date des dernières photos prises - date sur Terre : "+ manMis["max_date"] + "<br>";
				
				nbphotos = manMis["photos"].length; // nombre d'éléments du tableau manMis["photos"]
				datas = manMis["photos"][nbphotos - 1];
				cameras = datas["cameras"];
				
				manifeste += "Liste des caméras ayant pris les derières photos : <br>";
				
				document.getElementById("manifeste").innerHTML = manifeste;
			}
		}
		xhttp.open(apiMet, apiReq, true);
		xhttp.send();
		
		

	</script>

</html>
Article sous licence << Cliquez pour plus d’informations <<