Search code examples
javascriptasynchronousleafletresponse

Is it a way to extract a var from xmlhttp2 request in js?


Im new to javascript and php prog.

Im trying to extract a var from xhttp2 request to reuse it in my code. After multiply test I cant find a way to do it. I think i dont really get how asynchronous function works ..

my code :

    xhttp2.onreadystatechange = function() {
 if (this.readyState == 4 && this.status ==200) {
    let response = JSON.parse(xhttp2.responseText)
   let arrond = L.geoJSON(response).addTo(map1);}
 };
 xhttp2.open("GET", "js/test3.php",true);
 xhttp2.send();

im trying to extract the "arrond" var as a json

Thanks for your help !

Victor

here is my full code : it is on a leaflet project. The xhttp request is use to add data to my lealet map. The data comes from a postgreSQL data base and a php code to an array.

    //Initialisation de la carte 
var map1 = L.map('map1');
var osmUrl='http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib='Map data © OpenStreetMap contributors';
var osm = new L.TileLayer(osmUrl, {attribution: osmAttrib});
map1.setView([45.76, 4.85], 12);

//ajout de basemaps supplémentaires
var osmhumanUrl='https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png';
var osmhuman = new L.TileLayer(osmhumanUrl, {attribution: osmAttrib}).addTo(map1); 

var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
    attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
});

// //Appel de la couche equipement
var xhttp2 = new XMLHttpRequest();
// //lecture de la connexion au fichier php (2 variables cf. biblio)
xhttp2.onreadystatechange = function() {
     if (this.readyState == 4 && this.status ==200) {
//  //récupération du résultat de la requête sql et parcours de la couche :
      document.getElementById("demo").innerHTML =
      (xhttp2.responseText);
        let response = JSON.parse(xhttp2.responseText)
//         //appel de la couche
//      //console.log(response[0])
       let arrond = L.geoJSON(response).addTo(map1); 
     }
     };
xhttp2.open("GET", "js/test3.php",true);
xhttp2.send();


let Jardins =  L.geoJSON(jardins, 
    {
        onEachFeature: function (feature, layer) {
          layer.bindPopup(feature.properties.title);
        }
      }).addTo(map1);

//groupe de couche et de basemaps et layerControl
var baseMaps = {
    "OSM": osm,
    "OSM Humanitarian": osmhuman, 
    "Satellite": Esri_WorldImagery
};

var overlayMaps = {
    "Initiatives existantes": Jardins
};

//Ajout d'un bouton de gestion des calques
L.control.layers(baseMaps).addTo(map1);

Solution

  • Place the variable in global scope instead of nested scope

    declare it along with your other global variables like map1, osmUrl

    var map1 = L.map('map1');
    ...
    let arrond; ''here declare it
    
    //Appel de la couche equipement
    var xhttp2 = new XMLHttpRequest();
    //lecture de la connexion au fichier php (2 variables cf. biblio)
    xhttp2.onreadystatechange = function() {
       if (this.readyState == 4 && this.status ==200) {
          //récupération du résultat de la requête sql et parcours de la couche :
          document.getElementById("demo").innerHTML =
          (xhttp2.responseText);
            let response = JSON.parse(xhttp2.responseText)
             //appel de la couche
           arrond = L.geoJSON(response).addTo(map1); here assign the new value to the variable
         }
         };
    xhttp2.open("GET", "js/test3.php",true);
    xhttp2.send();
    

    outside onreadystatechange use it

    ..
    console.log(arrond)
    

    Edit

    I just noticed that you have the ajax property set to true. So everything is asynchronous.

    You can use a main function to get the result of the async operation to ensure the latter has arrived. You can use fetch api which is simpler in terms of code complexity comparing to the classic XMLHttpRequest.

     async function getData() {
            const response = await fetch("js/test3.php");
            const data = await response.json();
            console.log(data)
            const geojson = L.geoJSON(data, {
              onEachFeature
            });
            geojson.addTo(map1);
            map1.fitBounds(geojson.getBounds());
            return geojson;
          }
    

    and then create a main function and do all further json manipulations from now on regarding the geojson instance:

    async function main() {
                const arrond = await getData();
                console.log(arrond);
    }
        
    main(); // call it 
    

    here is an exampe with a free geojson api

    <!DOCTYPE html>
    <html>
    
    <head>
    
      <title>Quick Start - Leaflet</title>
    
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
      <link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
    
      <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
      <script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
    
    
    
    </head>
    
    <body>
      <div id="map1" style="width: 600px; height: 400px;"></div>
      <script>
        //Initialisation de la carte 
        var map1 = L.map('map1');
        var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
        var osmAttrib = 'Map data © OpenStreetMap contributors';
        var osm = new L.TileLayer(osmUrl, {
          attribution: osmAttrib
        });
        map1.setView([45.76, 4.85], 12);
    
        //ajout de basemaps supplémentaires
        var osmhumanUrl = 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png';
        var osmhuman = new L.TileLayer(osmhumanUrl, {
          attribution: osmAttrib
        }).addTo(map1);
    
        var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
          attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
        });
    
        function onEachFeature(feature, layer) {
          // does this feature have a property named popupContent?
          if (feature.properties && feature.properties.label) {
            layer.bindPopup(feature.properties.label);
          }
        }
    
    
        async function getData() {
          const response = await fetch("https://api-adresse.data.gouv.fr/search/?q=paris&type=street");
          const data = await response.json();
          console.log(data)
          const geojson = L.geoJSON(data, {
            onEachFeature
          });
          geojson.addTo(map1);
          map1.fitBounds(geojson.getBounds());
          return geojson;
        }
    
        async function main() {
          const arrond = await getData();
          console.log(arrond);
        }
    
        main();
      </script>
    
    </body>
    
    </html>