Функция JSON.parse в цикле for - PullRequest
       8

Функция JSON.parse в цикле for

0 голосов
/ 28 августа 2018

У меня проблема с функцией JSON.parse в цикле for. Автономный работает JSON.parse. В моем скрипте в цикле не работает. Это проблема с функцией в цикле? Понятия не имею.

Моя идея: анализировать JSON через Overpass API в цикле и генерировать JSON в виде txt в браузере. (скопируйте и вставьте его в текстовый файл и сохраните как * .js).

автономный:

function loadJSON(file, callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType('application/json');
    xobj.open('GET', file, true);
    xobj.onreadystatechange = function () {
        if (xobj.readyState == 4 && xobj.status == '200') {
            // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
            callback(xobj.responseText);
        }
    };
    xobj.send(null);
}

var lon = "9.841431";
var lat = "53.166591";

var overpassurl = 'http://overpass-api.de/api/interpreter?data=[out:json];is_in("' + lat + '","' + lon + '");out+body;%3E;out+skel;';

loadJSON(overpassurl, function (text) {

    var result = JSON.parse(text).elements[0].tags.name;

    document.getElementById("jsondiv").innerHTML = result;

});

JSFiddle: http://jsfiddle.net/5vqd7sm0/35/

Мой сценарий:

function loadJSON(file, callback) {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType('application/json');
    xobj.open('GET', file, true);
    xobj.onreadystatechange = function () {
        if (xobj.readyState == 4 && xobj.status == '200') {
            // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
            callback(xobj.responseText);
        }
    };
    xobj.send(null);
}

var lonlatarray = [
    [9.841431, 53.166591],
    [13.544482, 52.509910],
    [13.218674, 52.428120]
];

var jsontxt = "var jsonobject = { ";
jsontxt += '<br>';

for (let i = 0; i < lonlatarray.length; i++) {

    var lon = lonlatarray[i][0];
    var lat = lonlatarray[i][1];

    jsontxt += '"' + i + '": {';
    jsontxt += '<br>';
    jsontxt += '"coords":["' + lat + '","' + lon + '"],';
    jsontxt += '<br>';

    var overpassurl = 'http://overpass-api.de/api/interpreter?data=[out:json];is_in("' + lat + '","' + lon + '");out+body;%3E;out+skel;';

    jsontxt += '"bundesland":"' + loadJSON(overpassurl, function (text) {
        return JSON.parse(text).elements[0].tags.name;

    }) + '",';


    jsontxt += '<br>';
    jsontxt += '},';
    jsontxt += '<br>';

}

jsontxt += '}';

document.getElementById("jsondiv").innerHTML = jsontxt; 

JSFiddle: http://jsfiddle.net/bk13f7qh/43/

1 Ответ

0 голосов
/ 28 августа 2018

Вы получаете undefined, поскольку выходные данные из loadJson() недоступны во время выполнения, поскольку это функция async , которая не будет блокировать дальнейший код от выполнения и, поскольку В результате ваш код переходит к следующему запросу, прежде чем получить результат предыдущего запроса, и, поскольку предыдущего запроса еще нет, он выводится как undefined.

Как вы реализовали здесь:

jsontxt += '"bundesland":"' + loadJSON(overpassurl, function(text) {
       return JSON.parse(text).elements[0].tags.name;
}) + '",';

И затем вы пытаетесь добавить текстовое значение json к jsonDiv из jsontxt, сгенерированного вашей функцией.

Итак, поскольку вашим главным требованием является получение данных из запроса в цикле, вы должны изменить свою реализацию с того, что у вас есть сейчас, на следующее:

function exportJsonToFile(){

var jsontxt = document.getElementById("jsondiv"); //assigend jsontxt directrly to the control on which the data has to be assigned
var reqCount = 0; // a counter to be used for request context


function loadJSON(file, callback) {
  var xobj = new XMLHttpRequest();
  xobj.overrideMimeType('application/json');
  xobj.open('GET', file, false); 
  xobj.onreadystatechange = function() {
  if (xobj.readyState == 4 && xobj.status == '200') {
     // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
     callback(xobj.responseText);
     }
  };
  xobj.send(null);
}

var lonlatarray = [
 [9.841431, 53.166591],
 [13.544482, 52.509910],
 [13.218674, 52.428120]
 ];


jsontxt.innerHTML = "var jsonobject = { ";
jsontxt.innerHTML += '<br>';

for (let i = 0; i < lonlatarray.length; i++) {     
   var lon = lonlatarray[i][0];
   var lat = lonlatarray[i][1];

  jsontxt.innerHTML += '"' + i + '": {';
  jsontxt.innerHTML += '<br>';
  jsontxt.innerHTML += '"coords":["' + lat + '","' + lon + '"],';
  jsontxt.innerHTML += '<br>';



  var overpassurl = 'http://overpass-api.de/api/interpreter?data=[out:json];is_in("' + lat + '","' + lon + '");out+body;%3E;out+skel;';

  jsontxt.innerHTML += '"bundesland":"{' + i + '}",';

  loadJSON(overpassurl, function(text) {
   var name= JSON.parse(text).elements[0].tags.name;  
   jsontxt.innerHTML = jsontxt.innerHTML.replace('{'+reqCount+'}',name);
   reqCount++
  });

  jsontxt.innerHTML += '<br>';
  jsontxt.innerHTML += '},';
  jsontxt.innerHTML += '<br>';

}

 jsontxt.innerHTML += '}';
}

А потом просто вызвать функцию exportJsonToFile();

Итак, что я делаю в приведенном выше коде, так это то, что когда вы перебираете точки местоположения, я добавляю позицию данных, которые будут поступать в ваш json Text как {0}, {1}, { 2} как написано здесь:

jsontxt.innerHTML += '"bundesland":"{' + i + '}",'; 

и затем в обратном вызове loadJSON() я просто заменяю назначенные выше значения фактическими и увеличиваю переменную reqCount как:

var name= JSON.parse(text).elements[0].tags.name;
jsontxt.innerHTML = jsontxt.innerHTML.replace('{'+reqCount+'}',name);
reqCount++
...