根据彼此调用两个ajax调用但没有异步

时间:2017-05-01 04:47:37

标签: javascript jquery ajax

我正在从两个休息api创建动态菜单。菜单将由父/子关系创建。这意味着父ajax响应的id将传递给子ajax以获取子记录。

问题是,当我使用async false为我的孩子ajax调用时,我的网站变得很慢,当我删除它时,我的菜单不会呈现。一些帮助。

我的代码家长致电

var url;
url = "/_api/lists/getbytitle('GlobalTopNavMenu')/items?$select=Id,Title,Image,hasSubMenu,Link&$filter=Location eq 'GlobalNavigation'";
html = "<ul class='nav navbar-nav nav-topmrgn'>";
$.ajax({
  url: url,
  method: "GET",
  headers: {
    "Accept": "application/json; odata=verbose"
  },
  success: function(data) {
    $.each(data.d.results, function(i, item) {
      if (item.hasSubMenu == "Yes") {
        html += "<li class='dropdown yamm-fw borderLeftY'><a href='#' title='' class='dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>" + Res[item.Title] + "<b class='caret'></b></a>";
        html += getSubMenu(item.Id) + "</dl>";
        html += "<dl class=''><dd class='picHolder'><img alt='' src='/PublishingImages/" + item.Image + "'/></dd></dl></div></div></li></ul></li>";
      } else
        html += "<li class='yamm-fw borderLeftY'><a href='" + item.Link + "' title='' class='dropdown-toggle' role='link' aria-haspopup='true' aria-expanded='false'>" + Res[item.Title] + "</a></li>";
    })
    html += "</ul>";
    $("#navbar").empty();
    $("#navbar").append(html);
  }
});

儿童电话

function getSubMenu(id) {
  var url = "/_api/lists/getbytitle('GlobalSubNavMenu')/items?$select=Id,Title,Link,ParentMenu/Id,root&$filter=ParentMenu/Id eq " + id + "&$expand=ParentMenu/Id";
  var html = "";
  $.ajax({
    url: url,
    method: "GET",
    async: false,
    headers: {
      "Accept": "application/json; odata=verbose"
    },
    success: function(data) {
      if (data.d.results.length < 6)
        html += "<ul class='dropdown-menu width500 spaceLeft'>"; //
      else
        html += "<ul class='dropdown-menu width800 spaceLeft'>";
      html += "<li><div class='yamm-content'><div class='row'><dl class='col-sm-3 mega-menu colborderRight'>";
      $.each(data.d.results, function(i, item) {
        if (i !== 0 && i % 6 == 0)
          html += "</dl><dl class='col-sm-3 mega-menu colborderRight'><dd class=''><a href=/" + (item.root ? "" : lang) + item.Link + ">" + Res[item.Title] + "</a></dd>";
        else
          html += "<dd class=''><a href=/" + (item.root ? "" : lang) + item.Link + ">" + Res[item.Title] + "</a></dd>";
      });
    }
  });
  return html;
}

如果从子函数中删除async false,则菜单将不会呈现。那我怎么能这样做呢。

2 个答案:

答案 0 :(得分:1)

使用async: falsegetSubMenu()是异步的,因此,

  • getSubMenu()必须返回承诺(良好做法)或接受回调(不良做法),
  • 依赖于从getSubMenu()获取的数据的代码必须相应地计算。

这不是使用异步派生数据的最简单的介绍,特别是因为从循环内调用getSubMenu()

您需要了解以下内容:

  • jQuery.ajax()会返回一个承诺,允许您链接.then()。在解决这个问题时,你将从.then()的额外力量中获益,而不是“成功:”回调。
  • Array#map()将数组映射到您喜欢的任何新数组。此处Array#map()在创建getSubMenu()返回的承诺数组时特别有用。
  • jQuery.when()聚合多个承诺并返回一个承诺。

这是一个可以解决问题的镂空模式:

$.ajax({...})
.then(function(data) { // then() not success: ...
    var promises = data.d.results.map(function(item) {
        if (item.hasSubMenu == 'Yes') {
            return getSubMenu(item.Id).then(function(subMenu) {
                return '...'; // build and return an HTML string here, including the `subMenu` created by `getSubMenu()`.
            });
        } else {
            return '...'; // return hard-coded HTML. 
        }
    });
    // At this point, promises is an array comprising some unknown mix of jQuery promises and HTML strings.
    return jQuery.when.apply(null, promises).then(function(/* each argument is an HTML fragment, as generated above */) {
        var html = Array.prototype.join.call(arguments, ''); // slightly awkward syntax for joining `arguments` into a single string.
        $("#navbar").html('...' + html + '...');
    });
});

function getSubMenu(id) {
    var url = "...";
    return $.ajax({...}}) // getSubMenu() must return a promise.
    .then(function(data) { // then() not success: ...
        var html = "..."; // initial HTML fragment
        var arr = data.d.results.map(function(item) {
            return '...'; // build and return HTML based on item. 
        });
        // At this point, `arr` is an array of HTML fragments, that can be concatenated with Array#join().
        return html + '...' +  arr.join('') + '...'; // by using .then(), the promise returned by getSubMenu() will deliver whatever is returned here.
    });
}

完整:

var url = "/_api/lists/getbytitle('GlobalTopNavMenu')/items?$select=Id,Title,Image,hasSubMenu,Link&$filter=Location eq 'GlobalNavigation'";
$.ajax({
    url: url,
    method: "GET",
    headers: {
        "Accept": "application/json; odata=verbose"
    }
}).then(function(data) {
    var promises = data.d.results.map(function(item) {
        if (item.hasSubMenu == 'Yes') {
            return getSubMenu(item.Id).then(function(subMenu) {
                return '<li class="dropdown yamm-fw borderLeftY"><a href="#" title="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">' + Res[item.Title] + '<b class="caret"></b></a>' + subMenu + '<dl class=""><dd class="picHolder"><img alt="" src="/PublishingImages/' + item.Image + '"/></dd></dl></div></div></li></ul></li>';
            });
        } else {
            return '<li class="yamm-fw borderLeftY"><a href=#"' + item.Link + '" title="" class="dropdown-toggle" role="link" aria-haspopup="true" aria-expanded="false">' + Res[item.Title] + '</a></li>';
        }
    });
    return $.when.apply(null, promises).then(function() {
        $("#navbar").html('<ul class="nav navbar-nav nav-topmrgn">' + Array.prototype.join.call(arguments, '') + '</ul>');
    });
});

function getSubMenu(id) {
    var url = "/_api/lists/getbytitle('GlobalSubNavMenu')/items?$select=Id,Title,Link,ParentMenu/Id,root&$filter=ParentMenu/Id eq " + id + "&$expand=ParentMenu/Id";
    return $.ajax({
        url: url,
        method: 'GET',
        headers: {
            'Accept': 'application/json; odata=verbose'
        }
    }).then(function(data) {
        var html = (data.d.results.length < 6) ? '<ul class="dropdown-menu width500 spaceLeft">' : '<ul class="dropdown-menu width800 spaceLeft">';
        html += '<li><div class="yamm-content"><div class="row">';
        var arr = data.d.results.map(function(item) {
            return '<dd class=""><a href=/' + (item.root ? '' : lang) + item.Link + '>' + Res[item.Title] + '</a></dd>';
        });
        return html + '<dl class="col-sm-3 mega-menu colborderRight">' +  arr.join('') + '</dl>';
    });
}

答案 1 :(得分:0)

您可以稍微修改一下您的功能

func tabBarController(_ tabBarController: UITabBarController, 
                     didSelect viewController: UIViewController)
{
    if self.tabBar.selectedItem == messageTab as UITabBarItem {
        messageBadge = 0
    }
}

getSubMenu将有一个回调函数作为param,并返回生成的子菜单。

var url;
url = "/_api/lists/getbytitle('GlobalTopNavMenu')/items?$select=Id,Title,Image,hasSubMenu,Link&$filter=Location eq 'GlobalNavigation'";
html = "<ul class='nav navbar-nav nav-topmrgn'>";
$.ajax({
  url: url,
  method: "GET",
  headers: {
    "Accept": "application/json; odata=verbose"
  },
  success: function(data) {
    var totalMenus = data.d.results.length;
    $.each(data.d.results, function(i, item) {
        getSubMenu(item, function (submenuMarkup) {
            html += submenuMarkup;
            if (totalMenus === (i+1)) {
                html += "</ul>";
                $("#navbar").empty();
                $("#navbar").append(html);
            }
        });
    });
  }
});