Comunitats, províncies, municipis. Migració a Node.js

De wikijoan
La revisió el 15:24, 22 feb 2022 per Joan (discussió | contribucions)
(dif) ← Versió més antiga | Versió actual (dif) | Versió més nova → (dif)
Salta a la navegació Salta a la cerca

Introducció

En la pràctica anterior has fet una mini-aplicació per navegar per les comunitats, províncies i municipis de l'EE. Anem ara a canviar la tecnologia del servidor, i anem a fer les nostres crides AJAX contra un servidor Node.js. És a dir, farem servir Javascript tan en el cantó del client com en el cantó del servidor.

Referències

Hem vist Node.js a teoria:

Desenvolupament

Servidor http amb Node.js. Codi mínim

El codi mínim per accedir a la base de dades de municipis: script node_http_server_simple.js:

//test:
//http://localhost:8080/search_prov?id_com=2

var http = require('http');
var mysql = require('mysql2');
var request = require('request'); //npm install request
var url = require('url'); //no cal instal·lar aquest mòdul


// Create a connection to MySql Server and Database
var connection = mysql.createConnection({
  host : 'localhost',
  port : 3306,
  database: 'municipis',
  user : 'alumne',
  password : 'keiL2lai',
  charset : 'utf8'
});


// Create a simple Web Server to respond to requests
http.createServer(function(req, res){
  // RECEIVED A REQUEST!
  console.log(req.url);

  res.setHeader("Content-Type", "text/html; charset=utf-8");
  res.writeHeader(200);

  var query = require('url').parse(req.url,true).query;
  var id_com = query.id_com;
  console.log(id_com);

  connection.query("SELECT id_prov,provincia from provincies where id_com="+id_com, function(err, rows){

  if(err != null) {
    res.end("Query error:" + err);
  } else {
    for (var i = 0; i < rows.length; i++) {
      console.log(rows[i].provincia);
      res.write(rows[i].provincia + '<br />');
    };
    res.end(""); //important
  }
});

}).listen(8080);

Hem d'arrencar el servidor, i des del navegador web podem accedir a la informació de les províncies. Per ex:

Hem hagut d'instal·lar els paquets request i url per tal de poder accedir a la informació del paràmetre que passem per GET (id_com=7)

$ npm install request
$ npm install url

Aplicació AJAX contra Node.js

Hem de modificar el nostre servidor per distingir si volem fer un llistat de les comunitats; volem llistar les províncies d'una comunitat; o volem llistar els municipis d'una província:

Ho farem mirant la url del request:

if (req.url.indexOf("comunitats")>=0) {
   console.log("COMUNITATS");
   ...
} else if (req.url.indexOf("search_prov")>=0) {
   console.log("PROVÍNCIES");
   ...
} else if (req.url.indexOf("search_mun")>=0) {
   console.log("MUNICIPIS");
   ...
}

Ara ja podem adaptar el codi que tenim de la pràctica anterior per fer crides contra el servidor http implementat amb Node.js. Per exemple, quan carreguem l'aplicació (body onload) carregarem en una select box la llista de totes les comunitats.

script index.html:

...
<script>
function carregar_comunitats()
{
	var xmlhttp;
	var txt_opcions_comunitats;
	xmlhttp=new XMLHttpRequest();
	xmlhttp.onreadystatechange=function()
	{
		if (xmlhttp.readyState==4 && xmlhttp.status==200)
		{
			txt_opcions_comunitats = xmlhttp.responseText;
			//alert(txt_opcions_comunitats);
			var comunitats = "";
			comunitats = "<select name=\"comunitat\" onchange=\"canvi_comunitat(this.value)\">";
			comunitats += txt_opcions_comunitats;
			comunitats += "</select>";

			document.getElementById('comunitats').innerHTML = comunitats;
		} else {
			document.getElementById('comunitats').innerHTML = "<img src=\"img/ajax_wait.gif\" />";
		}
	}
	xmlhttp.open("GET","http://localhost:8080/comunitats",true);
	xmlhttp.send();

}
...
</script>
...

I la cerca de les comunitats està implementada en el servidor Node.js de la següent manera:

node_http_server.js:

...
// Create a simple Web Server to respond to requests
http.createServer(function(req, res){
  // RECEIVED A REQUEST!
  console.log(req.url);

  if (req.url.indexOf("comunitats")>=0) {
    console.log("COMUNITATS");
    res.setHeader('Access-Control-Allow-Origin', '*'); //funciona

    res.setHeader("Content-Type", "text/html; charset=utf-8");
    res.writeHeader(200);
    connection.query("SELECT * from comunitats", function(err, rows){

      if(err != null) {
        res.end("Query error:" + err);
      } else {
        for (var i = 0; i < rows.length; i++) {
          console.log(rows[i].comunitat);
          res.write("<option value=\"" + rows[i].id_com + "\">" + rows[i].comunitat + "</option>");
        };
        res.end("");
      }

    });

  }

}).listen(8080);

Per tal de no tenir problemes amb l'origen del Request hem hagut de ficar la línia:

res.setHeader('Access-Control-Allow-Origin', '*');

Versions

v1.

  • NodeJS en el servidor. Des de NodeJS es fan els accessos a la base de dades de municipis. El servidor retorna al client una llista de comunitats/províncies/municipis separats amb caràcters delimitadors (això ho volem millorar en la següent versió).

v2.

  • Utilitzem la Fetch API per fer les crides asíncrones al servidor.
  • En el servidor (NodeJS) construïm una cadena amb format JSON que serà el format d'intercanvi amb el client (en la versió 3 això ho millorarem).

v3. Orientem el codi a POO

  • En el servidor (NodeJS) creem un objecte JSON de les comunitats/províncies/municipis, i ara el codi és més elegant (i menys procliu a errors de sintaxi). Però per enviar l'objecte JSON al client l'hem de convertir a cadena (JSON.stringify).
  • En el client creem les selects i options amb createElement i queda un codi més elegant (però potser més complicat).

v4.

En les versions anteriors hem fet un if dins el servidor NodeJS per saber si estem cercant les comunitats, províncies o municipis. Aquesta part la podem fer més elegant fent que el servidor node_http_server.js sigui més petit, i redirigint el codi als scripts comunitats.js, search_prov.js i search_mun.js, que tindran la lògica de connectar-se a la base de dades, cercar la informació que interessa, i construir l'objecte JSON que enviarem al client. Això ho aconseguim amb el següent codi mínim:

El servidor node http:

var http = require('http');
var url = require('url');

// Create a simple Web Server to respond to requests
http.createServer(function(req, res){
    console.log(req.url);
    var urlparsed = url.parse(req.url,true);
    console.log(urlparsed.pathname);
    if (urlparsed.pathname!="/favicon.ico"){
        var funct = require('.'+urlparsed.pathname);
        funct.main(req,res);
    }
// The server will be listen on port 8080 
}).listen(8080);

Si cridem a http://localhost:8080/comunitats_prova, aleshors la variable urlparsed.pathname valdrà /comunitats_prova (incloent la barra).

i el script comunitats_prova.js pot incloure el següent codi:

exports.main = function(req,res){
  console.log("COMUNITATS");
  res.end("Andalusia, Catalunya,...");
};

NOTA: tant se val cridar

com

El truco d'aquesta manera de fer és que els mòduls es poden exportar, i això ho fem amb les línies:

var funct = require('./comunitats');
funct.main(req,res);

i dins del codi de comunitats.js trobem la línia:

exports.main = function(req,res){
...

Al mètode main li podem posar el nom que vulguem, i podem tenir definits diferents mètodes.

Més informació:

Feina per l'alumne

Has d'adaptar l'aplicació de la pràctica anterior, que et permetia navegar per totes les comunitats, províncies i municipis, a la tecnologia Node.js en el servidor. Igual que hem vist en el codi de classe, has d'orientar el codi a JSON, a utilitzar objectes, i pots utilitzar la Fetch API en comptes de la forma més primitiva de fer les crides AJAX.

Tens una solució al final de la pràctica, però es recomana a l'alumne encaridament (encarecidamente en castellà) trobar una solució pròpia. En tot cas, i al final de tot, es pot consultar el codi proposat (que és el que s'ha vist a classe).

Solució

Tens disponible el codi que s'ha comentat a classe, amb les tres versions:

Entrega

Entregaràs al Classroom tot el projecte empaquetat en un zip. Quan ho tinguis funcionant, ensenya-ho al professor, o sinó fes un screencast del funcionament de l'aplicatiu, comentant el resultat final i les parts més importants del codi.


creat per Joan Quintana Compte, febrer 2022