2

I am trying to parse a JSON object received from my server. This is my server's response:

[
  {
    "idPais": "1",
    "nombre": "España"
  },
  {
    "idPais": "2",
    "nombre": "Grecia"
  },
  {
    "idPais": "3",
    "nombre": "Holanda"
  },
  {
    "idPais": "4",
    "nombre": "Finlandia"
  },
  {
    "idPais": "5",
    "nombre": "Suiza"
  }
]

In my script, I tried to get the objects with one array, but resp is always undefined.

function loadCountries(cont) { // Listado de paises con contenidos
  var i = 0;
  var method = 'GET';
  var path = appConstants.requestCountriesURL(cont);
  console.log(path);
  var xhr = new XMLHttpRequest();   
  xhr.onreadystatechange = function() {
    alert('Status es: ' + xhr.status + 'State es: ' + xhr.readyState);
    if(xhr.readyState == 4 && xhr.status == 200) {
      alert('Recogiendo respuesta...');
      resp = xhr.responseText;
    }
  }
  xhr.open(method, path, false); // Creamos la peticion
  resp = xhr.send(); // Guardamos la respuesta
  if(resp == false || resp == undefined) {
    alert('La lista de paises no se pudo obtener');
    return resp;
  } else {
    alert('La lista de paises se obtuvo correctamente');
    console.log(resp);
    var listaPaises = JSON.parse(resp);
    return listaPaises;
  }
}

The error shown is the following:

Uncaught SyntaxError: Unexpected token u in JSON at position 0

Edit with solution 1:

function checkCountries(i){
    alert('oncheckCountries');
    var answer=$('input[name^="radio-choice"]:checked').val();
    alert('val es: '+ answer);
    $('#divPaises').css('display','block');
    getCountries(answer);

}
function getCountries(continente){
    alert('on getCountries');
    loadCountries(continente);
}
function loadCountries(cont){ //Listado de paises con contenidos
    var i = 0;
    var method = 'GET';
    var path = appConstants.requestCountriesURL(cont);
    console.log (path);
    var xhr = new XMLHttpRequest(); 
    xhr.onreadystatechange = function(){
        alert('Status es: '+xhr.status+'State es: '+xhr.readyState);
        if(xhr.readyState == 4 && xhr.status == 200){
            alert('Recogiendo respuesta...');
            resp = xhr.responseText;
            if(resp == false || resp == undefined){
                alert('La lista de paises no se pudo obtener');
                return resp;
            }
            else{
                    alert('La lista de paises se obtuvo correctamente');
                    console.log(resp);
                    var listaPaises = JSON.parse(resp);
                    console.log(listaPaises[0]);
                    var size = Object.keys(listaPaises).length;
                    var select = document.createElement('select');
                    alert('Select creado');
                    select.name = 'selectPais';
                    select.id = 'selectPais';
                    for(i=0;i<size ;i++){
                            var option = document.createElement('option');
                            option.id = listaPaises[i].idPais;
                            option.value = listaPaises[i].nombre;
                            option.appendChild(document.createTextNode(listaPaises[i].nombre));
                            alert(option.getAttribute('value'));
                            select.appendChild(option);
                            }
                    document.getElementById('divPaises').appendChild(select);
                }
        }
    }
    xhr.open(method, path, true); //Creamos la peticion
    resp = xhr.send(); // Guardamos la respuesta    
}
Asier
  • 461
  • 9
  • 19
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – JJJ Nov 24 '16 at 18:46
  • 1
    Shouldn't you check the `resp` after you get the response back? Right now you are checking its even before the server has sent you response back .. – Rajshekar Reddy Nov 24 '16 at 18:51
  • totally not duplicated of that post. – Asier Nov 24 '16 at 18:51
  • You are assign in the wrong place a value to `resp`. I think that you don't need this line `resp = xhr.send();` , you are getting the answer here `resp = xhr.responseText;` – Rafael Passarela Nov 24 '16 at 18:55
  • ^ Since you're making it synchronous you can `resp = xhr.responseText;` right after `xhr.send();` as Rafael suggested. But I'd highly recommend to make it async to avoid blocking the entire page while waiting – nottu Nov 24 '16 at 19:13

2 Answers2

2

Your issue here is that you are using the result of xhr.send() as the response, when it's not. If you want to parse the response you have to do it in the onreadystatechange listener, using xhr.responseText, like this:

xhr.onreadystatechange = function(){
    alert('Status es: '+xhr.status+'State es: '+xhr.readyState);
    if(xhr.readyState == 4 && xhr.status == 200){
        alert('Recogiendo respuesta...');
        resp = xhr.responseText;

        if(resp == false || resp == undefined){
            alert('La lista de paises no se pudo obtener');
        } else {
            alert('La lista de paises se obtuvo correctamente');
            console.log(resp);
            var listaPaises = JSON.parse(resp);
        }
    }
}

Also, you cannot return the response since that the request is asynchronous, so you have to either do everything inside your function, or use a callback function, like this:

function loadCountries(cont, callback) { // use a callback
    var i = 0;
    var method = 'GET';
    var path = appConstants.requestCountriesURL(cont);
    console.log (path);
    var xhr = new XMLHttpRequest();

    xhr.onreadystatechange = function(){
        alert('Status es: '+xhr.status+'State es: '+xhr.readyState);
        if(xhr.readyState == 4 && xhr.status == 200){
            alert('Recogiendo respuesta...');
            resp = xhr.responseText;

            if(resp == false || resp == undefined){
                alert('La lista de paises no se pudo obtener');
                callback(resp);
            } else {
                alert('La lista de paises se obtuvo correctamente');
                console.log(resp);
                var listaPaises = JSON.parse(resp);
                callback(listaPaises);
            }
        }
    }

    xhr.open(method, path, false);
    xhr.send();
}


// Create a callback
function myCallback(data) {
    // Do what you want with the data...
}

// Call the function like this...
function loadCountries(myCont, myCallback);
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
  • Thanks for your answer. In this case my request is syncronous, why can not i "return" values? – Asier Nov 24 '16 at 19:04
  • @Asier No, your request is asyncronous! You are using false on the last parameter of xhr.open(), so it's asynchronous. – Marco Bonelli Nov 24 '16 at 19:17
  • I think no, true is async, false is sync. https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests – Asier Nov 24 '16 at 19:30
  • @Asier ok you're right, so you should put true in your request, which is better. – Marco Bonelli Nov 24 '16 at 19:36
  • Yes, you are right, but if i put True, the code hops and i have not time to get data before return false. Wait a moment, im trying your answer. – Asier Nov 24 '16 at 19:40
  • 1
    I solved it. I will post the answer. I do all without callback function at the moment but i will put the code on it. I already tried it but when i try to get listaPaises array on another array in the callback function, it fails and destiny array stay "undefined". – Asier Nov 24 '16 at 19:51
1

It is an asynchronous call and you are trying to handle it as a synchronous one.

  xhr.onreadystatechange = function() {
    alert('Status es: ' + xhr.status + 'State es: ' + xhr.readyState);
    if(xhr.readyState == 4 && xhr.status == 200) {
      alert('Recogiendo respuesta...');
      resp = xhr.responseText;
      //Do your stuff with resp here
    }
  }
  xhr.open(method, path, false); // Creamos la peticion
  xhr.send(); //Send will not return anything 

Check here if you want more examples: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest

Guilhermevrs
  • 2,094
  • 15
  • 15