jQuery:附加异步加载的内容,维护顺序

时间:2012-05-21 20:28:40

标签: jquery asynchronous append

我有一系列要异步加载的内容网址,例如

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

我正在尝试使用AJAX加载每个代码段并将其附加到父<div>,从而维护数组中内容的顺序。由于我的其余代码的设置方式(以及出于性能原因),我希望以同步方式加载,使用async:false或链接{{ 1}}调用,如this similar question的答案所示。相反,我想在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元素;这看起来很难看,如果我能帮助它,我宁愿不把它粘在DOM上。

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

2 个答案:

答案 0 :(得分: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调用,可能会在某种循环中完成。

然后是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]);
      }
});

答案 1 :(得分: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,就像你现在一样。我不会等到所有东西都被加载,或者甚至按顺序添加它们。让订单最终像你现在一样自行完成。这就是Web浏览器在网页中加载图像的方式,而且有很深的理由。