2

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

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

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

以下代码有效:

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);
    });
});

……但我不喜欢它。特别是,我不喜欢用 ; 将订单附加到 DOM 元素上.data()。这看起来很难看,如果我能帮上忙,我宁愿不要把它放到 DOM 中。

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

4

2 回答 2

3

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

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 调用,这可能会在某种循环中完成。

然后是延迟对象承诺

$.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]);
      }
});
于 2012-05-21T21:28:54.633 回答
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 中,就像您现在所做的那样。我不会等到所有内容都加载完毕,甚至按顺序添加它们。让订单最终像您现在一样自行解决。这就是网络浏览器在网页中加载图像的方式,其中有很深的原因。

于 2012-05-21T20:46:49.770 回答