21

我仍在努力解决deferred问题,所以考虑到这一点,我对如何执行以下操作有疑问。

我和我的团队有 3 个单独.load()的方法,每个方法都获取一个特定的模板并将其附加到同一个容器中。如您所想,每次加载所需的时间不同,因此当内容加载时,它以“阶梯式”方式加载(1,然后 2,然后 3)。我想使用deferred对象并等到它们全部完成,然后同时附加它们以删除“阶梯”动作。

$('<div>').load(baseInfoTemplate, function () {
    var baseData = {
        // build some object
    };

    $.tmpl(this, baseData).appendTo($generalContainer);
});

所有三个调用都类似于上面的调用。

我怎样才能做到这一点?

4

5 回答 5

9

我在这种情况下使用下一个代码:

$.when(
    $.get('templates/navbar.tmpl.html', function(data) {
        $('#navbar').html(data);
    }),
    $.get('templates/footer.tmpl.html', function(data) {
        $('#footer').html(data);
    }),
    $.Deferred(function(deferred) {
        $(deferred.resolve);
    })
).done(function() {
    $.getScript("js/tools/jquery.min.js");
});

在我看来,它看起来比以前的实现更有条理,也更漂亮。

于 2013-09-06T10:21:24.550 回答
6

您可以将 存储promise objects在一个数组中,并用于$.when()确定这些承诺是否已履行。这可能看起来像这样:

var templates = [ ];

function createPromise( baseInfoTemplate ) {
    return $.Deferred(function( promise ) {
        $('<div>').load(baseInfoTemplate, function() {
            var baseData = { /* foobar */ };

            templates.push( baseData );
            promise.resolve();
        });
    }).promise();
}

var myPromises = [ ];

myPromises.push( createPromise( 'some data' ) );
myPromises.push( createPromise( 'even moar data' ) );
myPromises.push( createPromise( 'foo bar heay' ) );

$.when.apply( null, myPromises ).done( function() {
    templates.forEach(function( template ) {
        $.tmpl(this, template).appendTo($generalContainer);
    });
});

我在.apply()这里使用它是因为它接受一个数组作为函数调用的参数。所以基本上,我们将所有的 Promise 对象传递给.when().

示例:http: //jsfiddle.net/Hg77A/1/


更新:

正如 Alnitak 指出的那样,如果没有“成功”回调处理程序,上面的示例就没有多大意义。如果在使用 传输数据后触发“全部完成”处理程序就足够了.load(),那么您只需要from中.resolve()的承诺。这有任何意义吗?success handler.load()

于 2011-06-28T13:33:52.297 回答
5

$.load()不是为与 Deferred 对象一起使用而设计的,而且它还专门用于将内容立即放入页面中。

要解决后一个问题,您要么必须在 DOM 外部渲染整个容器,然后在它们全部完成后将其放入,要么您需要累积三个结果,然后一次性将它们全部放入。

下面的过程使用后一种方法:

  1. 改为使用,并创建一个由返回的对象$.get()组成的数组jqXHR$.get()

  2. 也将每个返回的片段存储$.get()在一个数组中

  3. 用于$.when.apply($, myArray).done(function() { ... })应用模板并将它们放入 DOM

http://jsfiddle.net/alnitak/WW3ja/

于 2011-06-28T13:49:12.127 回答
2

这是一个小 jQuery 插件的要点,它向一组 jQuery 元素添加了 loadThen 函数。它基本上是 load() 没有回调,它返回一个仅在内容加载并插入到选定元素集中后才解析的承诺。

它基本上是 jQuery 自己的 load() 代码的复制/粘贴,除了它从实际的 ajax 调用返回承诺。如果 ajax 失败,这可以让您获得拒绝的承诺。

由于它基于 load() 功能,因此您可以在 url 后添加一个选择器,以空格分隔,以仅获取加载的 html 的片段。


示例 1:将该站点的主页加载到 id="container" 的元素中

$('#container').loadThen('/').then(function () {
    // loaded and ready.
}, function () {
    // error
});

示例2:将首页的页眉加载到本页的页眉中

$('h1').eq(0).loadThen('/ h1').then(function () {
    // loaded and ready.
}, function () {
    // error
});

要点内容:

(function ($) {
    var _loadThen = $.fn.loadThen;
    $.fn.loadThen = function (url, params) {
        if (typeof url !== "string" && _loadThen) {
            return _loadThen.apply(this, arguments);
        }

        if(this.length <= 0) {
            return jQuery.Deferred().resolveWith(this, ['']);
        }

        var selector, type, response,
            self = this,
            off = url.indexOf(" ");

        if (off >= 0) {
            selector = jQuery.trim(url.slice(off));
            url = url.slice(0, off);
        }

        if (params && typeof params === "object") {
            type = "POST";
        }

        return jQuery.ajax({
            url: url,
            type: type,
            dataType: "html",
            data: params
        }).then(function (responseText) {
                self.html(selector ? jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) : responseText);
            return self;
        });
    };
}(jQuery));
于 2014-04-11T14:25:32.847 回答
2

我使用以下代码作为通用库

var loader = {};
(function(){
  var fn = {  
    promises: [],
    templates: [],

    loadTemplate: function( name ) {
      fn.promises.push(
        $.get( `templates/${name}.tmpl.html`,
               (html) => fn.templates.push( html )
        )
      );
    },

    main: function( templates, callback ) {
      templates.forEach( (template) => fn.loadTemplate( template ));
      $.when.apply( $, fn.promises ).done( function() {
        $( '<div id="templates">' ).html( fn.templates.join() ).appendTo( 'body' );
        callback();
      });
    }
  };

  /* EXPORTS */
  loader.main = fn.main;
})();

然后将其作为应用程序主 js 文件中的第一个函数调用。

function myMain() {
  ... // do all the things
}

$( document ).ready( function() {
  templates = [ 'thingies', 'wotsits', 'oojamaflips' ];
  loader.main( templates, () => myMain());
});
于 2014-07-22T10:35:43.673 回答