Вложенный Ajax не выполняется в последовательности - PullRequest
0 голосов
/ 28 февраля 2020

Я использую geonames api, которые получают географическую информацию. Я пытаюсь получить название штата в стране, используя функцию getStateInfo, а затем я пытаюсь получить города в штате, используя функцию getCityInfo. Я хотел получить одно состояние, а затем города в этом состоянии, но приведенный ниже код сначала выполняет функцию getStateInfo, а затем переходит к следующей функции getCityInfo, из-за этой проблемы я не могу отобразить правильные города в состоянии. Можно ли напечатать один штат, а затем напечатать все города в одном штате?

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script type="text/javascript">

        $(document).ready(function () {
            var finalList = ''
            getStateInfo().then(
                function (statedata, status, jqXHR) {
                    var countryName = statedata["geonames"][0].countryName;
                    var stateName = ''
                    var fullStateList = ''
                    var fullCityName;
                    $("#Level1").text(countryName);                    
                    for (i = 0; i < statedata["geonames"].length; i++) {
                        getCityInfo(statedata["geonames"][i].geonameId).then(
                            function (citydata, status, jqXHR) {
                                for (i = 0; i < citydata["geonames"].length; i++) {
                                    cityName = citydata["geonames"][i].toponymName                                
                                    console.log(cityName)
                                }
                            },
                            function (jqXHR, status, error) {
                                var err = eval("(" + jqXHR.responseText + ")");
                                alert("fail");
                                
                            });
                        stateName = "<li>" + statedata["geonames"][i].adminName1 + "</li>"
                        fullStateList += stateName;
                    }                    
                    $("#Level2").append(fullStateList);
                },
                function (jqXHR, status, error) {
                    var err = eval("(" + jqXHR.responseText + ")");
                    alert("fail");
                    console.log(err.Message);
                });
        });

        function getCityInfo(stateGeoId) {
            var dfd = $.Deferred();
            dfd = $.ajax({
                url: "http://api.geonames.org/childrenJSON?geonameId=" + stateGeoId + "&username=mydev199&hierarchy=geography",
                contentType: 'application/json',
                method: 'GET',
                dataType: "jsonp",                
            });
            return dfd.promise();
        }

        function getStateInfo() {
            var dfd = $.Deferred();
            dfd = $.ajax({
                url: "http://api.geonames.org/childrenJSON?geonameId=6252001&username=mydev199&hierarchy=geography",
                contentType: 'application/json',
                method: 'GET',
                dataType: "jsonp",                
            });
            return dfd.promise();
        }
    </script>
</head>
<body>
    <div id="ApplicationResults" class="resultSet">
        <ul id="myUL">
            <li>
                <span class="caret" id="Level1"></span>
                <ul class="nested" id="Level2"></ul>
            </li>
        </ul>
    </div>
</body>
</html>

1 Ответ

0 голосов
/ 28 февраля 2020

Я не уверен, какой именно конечный вывод вы хотите, но вот общая структура для получения всех данных, а затем вставки их на страницу, сохраняя все данные в порядке:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script type="text/javascript">

        $(document).ready(function () {
            var finalList = ''
            getStateInfo().then(function (statedata, status, jqXHR) {
                var countryName = statedata["geonames"][0].countryName;
                var stateName = ''
                var fullStateList = ''
                var fullCityName;
                $("#Level1").text(countryName);
                // loop through  all the items and get their data
                // let Promise.all() collecta all the data in order for us, before we process it
                Promise.all(statedata.geonames.map(function(item) {
                    return getCityInfo(item.geonameId).then(function(cityInfo) {
                        return cityInfo.geonames.map(function(location) {
                            return {name: location.toponymName, code: location.adminCode1};
                        });
                    });
                })).then(function(data) {
                    // now insert all the data in the page
                    let spot = $("#myUL");
                    data.forEach(function(collection) {
                        console.log(collection);
                        let root = $("<li>");
                        root.append('<span class="caret" id="Level1">' + collection[0].code + '</span>');
                        let r = $('<ul class="nested" id="Level2"></ul>');
                        collection.forEach(function(region) {
                            r.append('<li>' + region.name + '</li>');
                        });
                        root.append(r);
                        spot.append(root);
                    });
                }).catch(function(err) {
                    console.log(err);
                });
            });
        });

        function getCityInfo(stateGeoId) {
            return $.ajax({
                url: "http://api.geonames.org/childrenJSON?geonameId=" + stateGeoId + "&username=mydev199&hierarchy=geography",
                contentType: 'application/json',
                method: 'GET',
                dataType: "jsonp",                
            });
        }

        function getStateInfo() {
            return $.ajax({
                url: "http://api.geonames.org/childrenJSON?geonameId=6252001&username=mydev199&hierarchy=geography",
                contentType: 'application/json',
                method: 'GET',
                dataType: "jsonp",                
            });
        }
    </script>
</head>
<body>
    <div id="ApplicationResults" class="resultSet">
        <ul id="myUL">
            <li>
                <span class="caret" id="Level1"></span>
                <ul class="nested" id="Level2"></ul>
            </li>
        </ul>
    </div>
</body>
</html>

Если вы помещаете это в файл HTML и загружаете его в браузер, вы можете запустить его напрямую. Поскольку существует много вложенных запросов, выполнение занимает много времени. Вы можете настроить сгенерированный HTML по своему вкусу.

Этот код использует Promise.all() для параллельного выполнения всех запросов и сбора всех результатов по порядку. Тогда, только когда у нас есть все результаты по порядку, он затем итерирует их по порядку и построил HTML.

Я также упростил getStateInfo() и getCityInfo(), так как не было никакой причины создавать отложено в этих функциях. Вы можете просто вернуть обещание от $.ajax().

...