我正在尝试从API异步加载一堆数据,并且在加载所有数据时,我想触发一个事件,即所有数据都已加载。我遇到的问题是我使用的API将响应对象的数量限制为五个。我可能需要检索30-40个响应对象。
因此,我想做的是创建一个when- then语句,该语句循环遍历数据项并每5个请求一次,然后在所有项加载完毕后触发一个已加载事件。我遇到的问题是,当ajax请求成功之前,when- then语句已完成。
到我尝试过的代码上。
function loadsLotsOfStats(stats, dataType, eventName, dataName, callback) { var groupedStats = []; while (stats.length > 0) { groupedStats.push(stats.splice(0, 5).join('/')); } j$.when( groupedStats.forEach(function (d) { loadJSONToData(model.apiUrl.replace("{IDS}", d), "json", "", dataName, function (d) { /*console.log(d);*/ }, true) }) ).then(function () { j$(eventSource).trigger('dataLoaded', eventName); });
loadJSONToData函数基本上只是异步$ .ajax的包装函数。
所以是的,在实际加载数据之前就触发了该事件。同样由于某种原因,如果我尝试在when()中通过语法错误声明for循环?
有谁对我如何提出一堆Ajax请求有任何建议,然后等到它们全部完成后再触发事件?还是想解决我目前拥有的东西?
在此先感谢您的帮助。
可以按照您的要求进行操作。但是,您将请求发送到的服务器可能有一个原因限制了它们。作为从事Web开发工作并亲眼目睹DDOS,抓取以及其他滥用API的人,我建议遵循其限制。
话虽如此,这是您可以做到的。
$ .ajax实际上返回一个延迟的对象,因此您可以利用该对象。$ .when还可以接受任意数量的延迟对象。结合这两个事实可以解决您的问题。
var deferreds = []; $.each(groupedStats, function(index, stat){ deferreds.push( // No success handler - don't want to trigger the deferred object $.ajax({ url: '/some/url', data: {stat: stat}, type: 'POST' }) ); }); // Can't pass a literal array, so use apply. $.when.apply($, deferreds).then(function(){ // Do your success stuff }).fail(function(){ // Probably want to catch failure }).always(function(){ // Or use always if you want to do the same thing // whether the call succeeds or fails });
请注意,这不是竞争条件。尽管$ .ajax是异步的,但$ .each不是异步的,因此您的递延列表将是到达$ .when之前的总列表,并且$ .then / $。fail / $。always仅在它们全部完成后才被触发。
编辑:我忘了添加5s拆分,但这说明了总体思路。您可能可以从这里弄清楚如何将其应用于您的问题。顺便说一句,您可以只使用array.splice(0,5)从数组中获取下5个结果。.splice是可以安全使用的;如果元素总数少于5,则仅获取所有剩余元素。