【问题标题】:Fill/Generate multiple jQuery elements and sort them after ajax requests填充/生成多个 jQuery 元素并在 ajax 请求后对它们进行排序
【发布时间】:2018-02-25 12:34:21
【问题描述】:

我有一些 IDS,我想用它们来填充/生成一些 jQuery 对象。我在 ajax 请求中使用这些 IDS。 jQuery Objects 填满后,我想对它们进行排序。

必须在IE11中工作。

我的问题是: 目前我不知道最佳实践是怎样的,等待所有 ajax 请求以及所有 jQuery 对象被填充。

  • 我必须等到所有 ajax 请求都完成(所以 始终,独立于响应代码(如 .done 和 .fail))
  • 我必须等到所有 jQuery 对象由 ajax 请求的结果填充

问题总结:排序函数在项被填满之前被调用。

我试图将我的整个代码分解为一个简单的示例,也许有人可以在这里提供帮助:

function sortEntries(a, b) {
	var aa = ($(a).data('name') || '').toLowerCase(),
		bb = ($(b).data('name') || '').toLowerCase();
	return aa < bb ? -1 : aa > bb ? 1 : 0;
}

function getEntryInfo(infoObj, callback) {

	function getLabelByResult(result) {
		var name = '';
		switch (result) { // For this demo, we don't use the response data.
			case 'page-header':
				name = 'Hello World 1';
				break;
			case 'thumbnails':
				name = 'It works!';
				break;
			case 'nav':
				name = 'Great!';
				break;
			case 'btn-groups':
				name = 'BTN GROUP';
				break;
			default:
				name = 'NOT SET!'
		}
		return name;
	}

	return $.ajax({
		method: 'GET',
		url: infoObj.URI,
		cache: false
	}).done(function(data) {
		if ($.isFunction(callback)) {
			callback(true, {
				name: getLabelByResult(infoObj.element)
			});
		}
	}).fail(function() {
		if ($.isFunction(callback)) {
			callback(false, {
				name: getLabelByResult(infoObj.element)
			});
		}
	});
}

function setInfoForEntry(item$, config) {
	return getEntryInfo(config, function(isOk, responseObjInfo) {
		item$.attr('data-name', responseObjInfo.name || '').text(responseObjInfo.name || '');
	});
}

function generateItems() {
	var parentItem$ = $('body').append($('<ul/>').addClass('allItems').hide()),
		ids = ['page-header', 'thumbnails', 'nav', 'btn-groups'], // for testing purposes of course
		requests = [],
		extractedItems$;

	$.each(ids, function(ignorel, el) {
		var newItem$ = $('<li/>').addClass('idItem').on('click', function(e) {
			alert($(e.currentTarget).data('name'));
		});
		parentItem$.append(newItem$);
		requests.push(setInfoForEntry(newItem$, {
			URI: 'https://getbootstrap.com/docs/3.3/components/#/' + el,
			element: el
		}));
	});
	// HERE I HAVE TO ENSURE THAT:
	// -ALL AJAX REQUESTS ARE DONE
	// -ALL jQuery Elements are filled
	extractedItems$ = parentItem$.find('.idItem');
	extractedItems$.sort(sortEntries);
	extractedItems$.detach().appendTo(parentItem$);
	parentItem$.show();
}
$(document).ready(function() {
	generateItems();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body></body>

【问题讨论】:

  • 你为什么要做Ajax请求?您似乎没有在任何地方使用响应数据...?

标签: javascript jquery html ajax


【解决方案1】:

要等待多个承诺,jQuery 有$.when() 实用函数。另请参阅this threadthis thread(讨论这个的帖子很多,看看周围)。

我还稍微简化了您的代码,我认为这样更容易阅读:

function by(func) {
    return function (a, b) {
        var aa = func(a), bb = func(b);
        return aa < bb ? -1 : aa > bb ? 1 : 0;
    };
}    

$(function () {
    var things = {
        'page-header': 'Hello World 1',
        'thumbnails': 'It works!',
        'nav': 'Great!',
        'btn-groups': 'BTN GROUP'
    }, requests;

    requests = $.map(Object.keys(things), function (key) {
        return $.get('https://getbootstrap.com/docs/3.3/components/#/' + key)
            .then(function (data) {
                return $('<li class="idItem">', {text: things[key] || 'NOT SET!'})[0];
            });
    });

    $.when.apply($, requests).done(function () {
        // each argument here is a single <li> element
        var items = $(arguments).sort(by(function (el) {
            return ($(el).text() || '').toLowerCase();
        }));
        $('<ul class="allItems">').appendTo('body').append(items);
    }).fail(function (jqXhr, status, error) {
        // show error
    });
});

【讨论】:

  • 谢谢。我现在已经将它改编为我的代码,但遇到了麻烦:var items = $(arguments).sort(by(function (el) { return ($(el).data('name') || '').toLowerCase(); })); 参数包含三个值,全部未定义。你能帮帮我吗?
  • 嗯,我怀疑你改编的东西不太正确。 arguments 应该包含 4 个值,它们都是包含一个 &lt;li&gt; 元素的 jQuery 对象。
  • 好的,如果我将以下行更改为该示例似乎可以工作:[...].append(items);$('&lt;ul class="allItems"&gt;').appendTo('body').append($.map(items, function(el, ignore) {return el[0]})); 但现在我遇到了另一个问题。我的 .then 看起来像这样:.then(function(data) { parseEntryInfo(data, config, function(isOk, responseData) { return buildItem$(config, responseData); }); }); 方法 parseEntryInfo 需要有一个回调,因为我在那里也做必要的 ajax 请求。你知道如何在这种情况下返回 buildItem$ 吗?
  • 啊,你是对的。正如我所说,arguments 是包含 &lt;li&gt; 元素的 jQuery 对象。所以arguments 看起来像这样:[[&lt;li&gt;], [&lt;li&gt;], [&lt;li&gt;], [&lt;li&gt;]],但是对于.append(),我们实际上需要这个:[&lt;li&gt;, &lt;li&gt;, &lt;li&gt;, &lt;li&gt;]。我的错误,我已经对我的答案进行了必要的更改。当您单击答案下方的“已编辑...”链接时,您可以看到 diff #4 中的更改。
  • 除此之外,我已经替换了您的功能是有原因的。它们不必要地复杂。例如,您不需要任何回调,这就是 Promise 的用途。我鼓励您放弃这些函数,并采用我代码中演示的更多方法。
猜你喜欢
  • 2010-10-22
  • 1970-01-01
  • 2018-09-04
  • 2011-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多