【问题标题】:jQuery: Append asynchronously loaded content, maintaining orderjQuery:追加异步加载的内容,维护顺序
【发布时间】:2012-05-22 05:28:54
【问题描述】:

我有一组要异步加载的内容 URL,例如

var toLoad = ['snippet1.html', 'snippet2.html', ... ];

我正在尝试使用 AJAX 加载每个 sn-p 并将其附加到父 <div>,保持数组中内容的顺序。由于我的其余代码的设置方式(以及出于性能原因),我希望以同步方式加载,无论是使用async:false 还是通过链接.ajax() 调用,正如对this similar question 的回答所建议的那样。相反,我想将逻辑放入 AJAX 回调函数中,以根据索引正确放置加载的 sn-ps。

以下代码有效:

var $parent = $('#mydiv');
toLoad.forEach(function(url, i) {
    // load snippet
    $.get(url, function(snippet) {
        // attach order to DOM element
        snippet = $(snippet).data('order', i);
        // find the sibling with the next lowest order number
        var $prev = $parent
            .children()
            .filter(function() {
                return $(this).data('order') < i
            })
            .last();
        if ($prev[0]) snippet.insertAfter($prev); 
        else $parent.prepend(snippet);
    });
});

...但我不喜欢它。特别是,我不喜欢使用.data() 将订单附加到DOM 元素;这看起来很难看,如果可以的话,我宁愿不把它放到 DOM 中。

有没有更好的方法来实现将内容异步加载到具有预定义顺序的 div 中?

【问题讨论】:

  • 是否可以将所有加载推迟到获取所有值之后?然后您可以构建一个数组来跟踪每个请求的结果,并仅在获取所有 url 后附加到 DOM。
  • @DCoder - 这可能行得通 - 但它并不理想,因为我必须添加额外的逻辑来跟踪是否所有调用都已完成。

标签: jquery asynchronous append


【解决方案1】:

有一个简单的递归,等到一个完成后再开始下一个:

var toLoad = ['snippet1.html', 'snippet2.html', ....];
var $parent = $('#mydiv');
var i = 0;

getSnippet(toLoad[i]);

function getSnippet(url) {
    $.get(url, function(snippet) {
        $parent.append(snippet);
        if (i<toLoad.length) getSnippet(toLoad[i++]);
    });
}​

然后一次完成所有这些,只需将它们粘贴在一个数组中,一个接一个地运行 done() 函数以确保按顺序插入元素:

var toLoad = ['snippet1.html', 'snippet2.html', 'snippet3.html'];
var $parent = $('#mydiv');
var gets = [];

toLoad.forEach(function(url, i) {
    var XHR = $.get(url);
    gets.push(XHR);
});

gets[0].done(function(snippet) {
     $parent.append(snippet);
     gets[1].done(function(snippet) {
         $parent.append(snippet);
         gets[2].done(function(snippet) {
             $parent.append(snippet);
         });
     });
});
​

如果进行许多 ajax 调用,这可能会在某种循环中完成。

然后是deffered objectspromises

$.when($.get(toLoad[0]), 
       $.get(toLoad[1])
       $.get(toLoad[2])
      ).done(function(value1, value2, value3) {
      // value1 etc. are arguments resolved for the ajax requests, respectively
      // arguments are [ "success", statusText, jqXHR ]
        $parent.append(value1[2]+value2[2]+value3[2]);
      }
});

【讨论】:

    【解决方案2】:

    如果您的主要抱怨是使用 .data(),您可以维护自己的数组,将 dom 节点元素与值相关联。

    var map = [
        {order: 5, nodeReference: ...},
        {order: 9, nodeReference: ...},
        {order: 1, nodeReference: ...}
    ];
    function data(node) {
        // loop through map, comparing to nodeReference to get the order 
    }
    

    //然后 ...

        .filter(function() {
            return data(this) < i
        })
    

    您的代码大部分保持不变,除了在向 dom 附加内容时需要添加到地图。

    我会努力在加载后立即将内容逐步添加到 dom 中,就像您现在所做的那样。我不会等到所有内容都加载完毕,甚至按顺序添加它们。让订单最终像您现在一样自行解决。这就是网络浏览器在网页中加载图像的方式,其中有很深的原因。

    【讨论】:

    • 这是个好建议;您可以通过将 map 设为 DOM 元素数组、在特定索引处插入并检查 map.indexOf(this) 而不是循环遍历来使其更简单。
    • 是的,这可行。如果您可以对 map[node] = order; 之类的对象进行索引会更好,但 javascript 属性必须是标量,据我所知,DOMNode 不提供合适的唯一 ID,如哈希码或序列 ID,可能是用过。
    猜你喜欢
    • 2013-06-12
    • 1970-01-01
    • 2018-02-01
    • 2017-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-18
    相关资源
    最近更新 更多