等待$ .each在$ .getJSON内完成

时间:2015-01-13 19:02:10

标签: php jquery json

我想通过查询数据库中某个表的一列中的唯一属性来生成侧栏的链接列表。我打算创建这些链接,然后查询共享该值的所有条目。

我使用$.getJSON()方法获取数据并编辑DOM。我知道在$.getJSON()方法中使用JSON数组的唯一方法是在其上运行$.each(),因为for(i=0;i<object.key.length();i++)语句似乎不能在匿名回调中工作功能

我的JSON对象结构如下

{"M" : [
  {"category" : "value1"},
  {"category" : "value2"},
  {"category" : "value3"}],
"Q" : [
  {"category" : "same shit"},
  {"category" : "different heading"}]
}

我的代码中有问题的部分如下

$sidebar.html("<h1>Catalog</h1>");
$.getJSON("script.php", function(data) {
  $sidebar.append("<h2>Manufacturing</h2><ul>"); // open the <ul> tag
  $.each(data.M, function(i, row) {
    $sidebar.append("<li><a>" + row.category + "</a></li>");
  });
  $sidebar.append("</ul>"); // close out the <ul> tag AFTER the $.each
});

这使我的侧边栏的HTML采用

的形式
<h1>...</h1>
<h2>...</h2>
<ul>...</ul>
<li><a>...</a></li>
<li><a>...</a></li>
<li><a>...</a></li>

我发现令人难以置信的烦恼。我一直在尝试应用these three posts中建议的$.promise().done()策略,正好问这个问题,但这些问题都没有与{存在于PHP调用函数中的{1}}。我无法使脚本以正确的顺序构造无序列表。在附加任何列表项之前,它会一直关闭$.each()标记。

我已将<ul>.done()链接到.promise().done()$.each我追加,甚至连{{1}本身只是为了看看它是否可行(即使它工作也无法帮助我在脚本中添加更多数组并完成它)。

我非常沮丧,因为对三个引用帖子的回答都坚持$sidebar应该在移动到下一行之前完成,除非$.getJSON()涉及动画或AJAX调用完成的时间不容忽视。我的应用程序既没有这些陷阱,但似乎无论如何都是异步运行。

In this JFiddle您可以看到每个标记附加的标记不属于$.each()标记,因为CSS会使其变为绿色而不是红色。

2 个答案:

答案 0 :(得分:7)

问题是您正在调用.append()并附加无效的HTML。浏览器不允许将无效的html插入到dom中,因此会为您关闭<ul>,并且您将<li>添加到<ul>之外。

您应该单独创建<ul>,将新的<li>添加到该<ul>,然后将完成的 $sidebar.append("<h2>Manufacturing</h2>"); ul = $('<ul>'); for(...) { ul.append('<li>...</li>'); } $sidebar.append(ul); 插入到dom中。

{{1}}

答案 1 :(得分:5)

你肯定可以在匿名回调中运行for循环,你可能会失败,因为length是属性,而不是方法。此外,您的HTML被屠杀,因为您将部分元素附加到DOM:

<h2>Manufacturing</h2><ul>

无效,ul需要关闭:

$sidebar.html("<h1>Catalog</h1>");
$.getJSON("script.php", function(data) {
    $sidebar.append("<h2>Manufacturing</h2>"); // open the <ul> tag -- NO
    var ul = "<ul>";

    //for (var i = 0; i < data.M.length; i++)
    $.each(data.M, function(i, row) {
        ul += "<li><a>" + row.category + "</a></li>";
    });

    ul += "</ul>";
    $sidebar.append(ul);
});