【问题标题】:Nested Ajax not executing in sequence嵌套 Ajax 未按顺序执行
【发布时间】:2020-06-11 23:19:17
【问题描述】:

我正在使用 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>

【问题讨论】:

    标签: jquery html ajax promise geonames


    【解决方案1】:

    我不确定您想要的最终输出是什么,但这里有一个通用结构,用于获取所有数据,然后将其插入到页面中,同时保持所有数据有序:

    <!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()返回promise。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-28
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 2017-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多