我试图链接我写的一个插件的几个调用。该插件本身有两个可能的Ajax调用 - 内容存储服务以及手柄模板。我对两者都进行了缓存,但是在第一次加载时,卡的顺序经常会发生变化,因为某些调用比前一次调用要长一些。结果,卡的顺序改变,这在内容层次方面是有问题的。在这个例子中,我正在加载标记为研究和播客的卡片。
我按如下方式调用插件:
$('#research').getCards({
category: 'research',
}).getCards({
category: 'podcast'
});
该插件非常大,所以我只发布了最后一个Ajax调用(我想要返回它)。一旦从我的服务中获取数据,就会调用fetchTemplate函数,counter为0,length是函数初始化时card_data的长度。我想要这个函数递归,直到我的card_data数组中的每个项目都打印了一张卡片,然后它应该返回这个以允许下一次调用getCards。
$.fn.getCards = function(options) {
var defaults = {
target: this,
category: '',
},
settings = $.extend({}, defaults, options);
function fetchTemplate(card_data, counter, length) {
counter++;
var cardTemplate = '';
if (localStorage[cardTemplate] && settings.localStorageSupport) {
printCard(localStorage[cardTemplate], card_data[counter - 1]);
if (counter !== length) {
fetchTemplate(card_data, counter, length);
}
} else {
$.ajax({
url: '/templates/cards/' + cardTemplate + '.hbs.js',
type: 'GET',
dataType: 'text',
success: function(data) {
localStorage.setItem(cardTemplate, data);
printCard(data, card_data[counter - 1]);
return this // this is when I want to fire my chained call
if (counter !== length) {
fetchTemplate(card_data, counter, length);
}
}
});
}
}
};
我尝试过闭包,但这并没有奏效。我也试过return settings.target
。最后,我尝试在return this.each
中包装整个插件,但是在Ajax请求完成之前,每次触发都没有工作。我知道我可能会重写插件以调用只有一次调用getCards的类别数组,但我不想重写我的所有逻辑。
答案 0 :(得分:0)
您可以使用.queue()
和.promise()
按顺序执行异步任务。
您将context
的{{1}} $.ajax()
调用方法this
this
作为.then()
中的元素,在{{1}定义属性将.data()
设置为函数内的数组,并使用异步任务的结果填充数组。设置链this
以获取.then()
调用的结果,其中$.fn.getCards()
将设置为原始jQuery对象,异步任务的结果将在this
.data()
处访问1}}。然后,您可以再次致电this
,重复此过程。
.getCards()
$.fn.getCards = function(options) {
var el = this;
if (!this.data().results) {
this.data().results = [];
}
return this.queue("cards", $.map(options, function(item) {
return function(next) {
return $.Deferred(function(dfd) {
setTimeout(function() {
dfd.resolveWith(el, [item])
}, 1000)
})
.then(function(data) {
this.data().results.push(data);
return;
})
.then(next)
}
})).dequeue("cards").promise("cards")
}
$("body")
.getCards([1,2,3])
.then(function() {
console.log(this.data().results, this.get(0).tagName === "BODY");
return this.getCards([4,5,6])
})
.then(function() {
console.log(this.data().results, this.get(0).tagName === "BODY");
})