使用带有 Promise 的 jQuery 加载

发布于 2024-11-17 10:28:03 字数 666 浏览 3 评论 0原文

我仍在尝试解决 deferred以及什么不是,所以考虑到这一点,我有一个关于如何执行以下操作的问题。

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

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

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

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

我怎样才能实现这个目标?

I'm still trying to wrap my head around deferred and what not, so with this in mind I have a question on how to do the following.

My team and I have 3 separate .load() methods that each go grab a specific template and append that to the same container. Each load takes a different amount of time as you might think, so when the content loads, it loads in a 'stair step' fashion (1, then 2, then 3). I'd like to make use of deferred objects and wait until they are all done, then append them at the same time to remove the 'stair step' action.

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

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

All three calls are similar to the call above.

How can I achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

神经大条 2024-11-24 10:28:03

对于这种情况,我使用下一个代码:

$.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");
});

在我看来,它看起来比以前的实现更加结构化并且非常漂亮。

I use next code for this case:

$.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");
});

To my mind it looks more structured and pretty nice than previous implementations.

南风起 2024-11-24 10:28:03

您可以将 promise 对象 存储在数组中,并使用 $.when() 来查明这些 Promise 是否已履行。这可能看起来像这样:

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() 传输数据后触发“全部完成”处理程序就足够了,那么您只需要 .resolve() 中的承诺来自 .load()成功处理程序。这有什么意义吗?

You can store the promise objects in an array and use $.when() to find out if those promises are fullfilled. This could look like this:

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

I'm using .apply() here because it accepts an array as arguments for a function call. So basically, we're passing all promises objects to .when().

Example: http://jsfiddle.net/Hg77A/1/


Update:

as Alnitak pointed out, the above example wouldn't make much sense if there is no "success" callback handler. If it is just enough to fire the "all done" handler after you transfered the data with .load(), you just would need to .resolve() the promises within the success handler from .load(). Does that make any sense?

甜味拾荒者 2024-11-24 10:28:03

$.load() 并非设计用于延迟对象,而且它专门用于立即将内容放入页面中。

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

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

  1. 使用 $.get() 代替,并创建由 $.get( 返回的 jqXHR 对象组成的数组)

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

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

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

$.load() isn't designed for use with Deferred objects, and also it is intended specifically to drop stuff into the page immediately.

To solve that latter problem you either have to render the entire container outside the DOM, and then drop it in when they're all done, or you need to accumulate the three results and then put them all in in one go.

The process below uses the latter approach:

  1. Use $.get() instead, and create an array of the jqXHR objects returned by $.get()

  2. Store the return fragments from each $.get() in an array too

  3. Use $.when.apply($, myArray).done(function() { ... }) to apply the templates and put them into the DOM

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

奈何桥上唱咆哮 2024-11-24 10:28:03

这是一个小 jQuery 插件的要点,该插件添加了一个 loadThen 函数一组 jQuery 元素。它基本上是没有回调的 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
});

Gist 内容:

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

Here's a Gist for a little jQuery plugin that adds a loadThen function to a set of jQuery elements. It's basically load() without the callback and it returns a promise that is only resolved after the content is loaded and inserted into the set of selected elements.

It's basically a copy/paste of jQuery's own load() code except it returns the promise from the actual ajax call. This lets you get a rejected promise if the ajax fails.

Since it's based on the load() functionality, you can add a selector after the url seperated by a space to get only a fragment of the loaded html.


Example 1: Load the home page of this site into element with id="container"

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

Example 2: Load the home page's header into this page's header

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

Gist contents:

(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));
分開簡單 2024-11-24 10:28:03

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

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

I use the following code as a generic library

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

then call it as the first function in the application's main js file.

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

$( document ).ready( function() {
  templates = [ 'thingies', 'wotsits', 'oojamaflips' ];
  loader.main( templates, () => myMain());
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文