当所有产品都已加载时使用 Deferred
Using Deferred when all products have loaded
我有一个带轮播的页面,每次幻灯片更改时都会发送一个 ajax 请求,并将生成与幻灯片相关的产品到底部的另一个轮播中。
当每张幻灯片发生变化时,产品已成功绘制 Ajax,但我需要在 ajax 请求加载后启动带有产品的滑块。现在,滑块会尝试在请求完成之前进行初始化。
在我添加的代码底部,每个函数将每个 getProducts 函数添加到一个数组,然后在完成后初始化滑块。尽管在控制台中消息 'this is initialized' 发生在 Ajax 请求中的 'success' 消息之前。
我是不是在这个例子中使用了deferred错误导致了这个问题?
var products = [],
uniqueProducts = [],
defs = [];
var el;
$('.your-class [data-slick-index="' + currentSlide + '"] a').each(function(i) {
el = $(this).attr("href");
products.push(el);
$.each(products, function(j, el) {
if ($.inArray(el, uniqueProducts) === -1)
uniqueProducts.push(el);
console.log("pushed" + uniqueProducts);
});
});
function getProducts(el) {
var def = new $.Deferred();
var url = el;
$.get(url, function(data) {
var imageArray = data.match(/<img itemprop="image" [\S\s]*?>/ig);
var $image = $(imageArray[0]);
var imageUrl = $image.attr('src');
var name = $image.attr('title');
var priceArray = data.match(/<p class="price">[\S\s]*?<\/p>/ig);
var priceEl = $(priceArray[0]).find('[itemprop=price]');
priceEl.children().remove();
var price = priceEl.text() ? '$' + priceEl.text() : '';
$( ".carousel2" ).append( '<div><img src=\" '+ imageUrl +'\"></div>');
console.log("success");
def.resolve();
});
return def.promise();
}
$.each(uniqueProducts, function(i, el) {
defs.push(getProducts(el));
});
$.when($,defs).done(function () {
$('.carousel2').slick({ speed: 500, autoplay: false, autoplaySpeed: 4000, arrows:false });
console.log("this is initialized");
});
}
我有一段时间没玩过 $.when
,但我认为您可以在不必创建 $.Deferred()
实例的情况下使用它,因为 $.get
将 return这个给你。
可能尝试使用 getProducts
return $.get
而不是 def.promise
并删除对 def
?
的任何引用
希望能帮到你!
p.s 我找到了一些我使用这个 $.when
的旧代码,看看我如何将它与 $.get
一起使用。我已经简化了它,下面的内容应该可以工作。
$.when([
$.get("data/a.json"),
$.get("data/b.json"),
$.get("data/c.json")
]).done(function (t1, t2, t3) {
app.a = t1[0];
app.b = t2[0];
app.c = t3[0];
});
归功于 this answer,构建 uniqueProducts
将简化为两个单行。
var uniqueProducts = $('.your-class [data-slick-index="' + currentSlide + '"] a').map(function(el) {
return $(el).attr('href');
}).get().filter(function(href, pos, self) {
return self.indexOf(href) == pos;
});
而getProducts()
应该简化如下:
function getProducts(url) {
return $.get(url).then(function(data) {
var image = $(data.match(/<img itemprop="image" [\S\s]*?>/ig)[0]);
var price = $(data.match(/<p class="price">[\S\s]*?<\/p>/ig)[0]).find('[itemprop=price]').children().remove().end().text();
return {
name: image.attr('title'),
image: image,
price: price ? '$' + price : ''
};
});
}
请注意,getProducts()
现在没有副作用,但 returns 是一个数据对象。
然后通过使用uniqueProducts.reduce(...)
,您可以调用getProducts()
和处理promise传递的数据。
假设一切都发生在一个函数中,你最终会得到这样的结果:
function initializeCarousel() {
return $('.your-class [data-slick-index="' + currentSlide + '"] a')
.map(function(el) {
return el.href;
})
.get()
.filter(function(href, pos, self) {
return self.indexOf(href) == pos;
})
.reduce(function(sequence, url) {
var productPromise = getProducts(url);
return sequence
.then(function() {
return productPromise;
})
.then(function(dataObj) {
$(".carousel2").append(dataObj.image);
// ... dataObj.name ...
// ... dataObj.price ...
}, function() {
return sequence;//skip over error
});
}, $.when())//resolved starter promise for the reduction
.then(function () {
$('.carousel2').slick({ speed: 500, autoplay: false, autoplaySpeed: 4000, arrows:false });
console.log("this is initialized");
});
}
这个特殊的 .reduce 模式的特点是:
- ajax 调用并行。
- 如果需要,可以非常简单地转换串行调用。
- 附加到旋转木马的图像顺序将与缩减数组一致,即 "right order"。
- 任何个人的ajax错误都不会破坏整个企业。
- 不需要中间
promises
数组或 jQuery 的繁琐 $.when.apply(null, promises)
(或其他库中更友好的 .all()
)。
我有一个带轮播的页面,每次幻灯片更改时都会发送一个 ajax 请求,并将生成与幻灯片相关的产品到底部的另一个轮播中。
当每张幻灯片发生变化时,产品已成功绘制 Ajax,但我需要在 ajax 请求加载后启动带有产品的滑块。现在,滑块会尝试在请求完成之前进行初始化。
在我添加的代码底部,每个函数将每个 getProducts 函数添加到一个数组,然后在完成后初始化滑块。尽管在控制台中消息 'this is initialized' 发生在 Ajax 请求中的 'success' 消息之前。
我是不是在这个例子中使用了deferred错误导致了这个问题?
var products = [],
uniqueProducts = [],
defs = [];
var el;
$('.your-class [data-slick-index="' + currentSlide + '"] a').each(function(i) {
el = $(this).attr("href");
products.push(el);
$.each(products, function(j, el) {
if ($.inArray(el, uniqueProducts) === -1)
uniqueProducts.push(el);
console.log("pushed" + uniqueProducts);
});
});
function getProducts(el) {
var def = new $.Deferred();
var url = el;
$.get(url, function(data) {
var imageArray = data.match(/<img itemprop="image" [\S\s]*?>/ig);
var $image = $(imageArray[0]);
var imageUrl = $image.attr('src');
var name = $image.attr('title');
var priceArray = data.match(/<p class="price">[\S\s]*?<\/p>/ig);
var priceEl = $(priceArray[0]).find('[itemprop=price]');
priceEl.children().remove();
var price = priceEl.text() ? '$' + priceEl.text() : '';
$( ".carousel2" ).append( '<div><img src=\" '+ imageUrl +'\"></div>');
console.log("success");
def.resolve();
});
return def.promise();
}
$.each(uniqueProducts, function(i, el) {
defs.push(getProducts(el));
});
$.when($,defs).done(function () {
$('.carousel2').slick({ speed: 500, autoplay: false, autoplaySpeed: 4000, arrows:false });
console.log("this is initialized");
});
}
我有一段时间没玩过 $.when
,但我认为您可以在不必创建 $.Deferred()
实例的情况下使用它,因为 $.get
将 return这个给你。
可能尝试使用 getProducts
return $.get
而不是 def.promise
并删除对 def
?
希望能帮到你!
p.s 我找到了一些我使用这个 $.when
的旧代码,看看我如何将它与 $.get
一起使用。我已经简化了它,下面的内容应该可以工作。
$.when([
$.get("data/a.json"),
$.get("data/b.json"),
$.get("data/c.json")
]).done(function (t1, t2, t3) {
app.a = t1[0];
app.b = t2[0];
app.c = t3[0];
});
归功于 this answer,构建 uniqueProducts
将简化为两个单行。
var uniqueProducts = $('.your-class [data-slick-index="' + currentSlide + '"] a').map(function(el) {
return $(el).attr('href');
}).get().filter(function(href, pos, self) {
return self.indexOf(href) == pos;
});
而getProducts()
应该简化如下:
function getProducts(url) {
return $.get(url).then(function(data) {
var image = $(data.match(/<img itemprop="image" [\S\s]*?>/ig)[0]);
var price = $(data.match(/<p class="price">[\S\s]*?<\/p>/ig)[0]).find('[itemprop=price]').children().remove().end().text();
return {
name: image.attr('title'),
image: image,
price: price ? '$' + price : ''
};
});
}
请注意,getProducts()
现在没有副作用,但 returns 是一个数据对象。
然后通过使用uniqueProducts.reduce(...)
,您可以调用getProducts()
和处理promise传递的数据。
假设一切都发生在一个函数中,你最终会得到这样的结果:
function initializeCarousel() {
return $('.your-class [data-slick-index="' + currentSlide + '"] a')
.map(function(el) {
return el.href;
})
.get()
.filter(function(href, pos, self) {
return self.indexOf(href) == pos;
})
.reduce(function(sequence, url) {
var productPromise = getProducts(url);
return sequence
.then(function() {
return productPromise;
})
.then(function(dataObj) {
$(".carousel2").append(dataObj.image);
// ... dataObj.name ...
// ... dataObj.price ...
}, function() {
return sequence;//skip over error
});
}, $.when())//resolved starter promise for the reduction
.then(function () {
$('.carousel2').slick({ speed: 500, autoplay: false, autoplaySpeed: 4000, arrows:false });
console.log("this is initialized");
});
}
这个特殊的 .reduce 模式的特点是:
- ajax 调用并行。
- 如果需要,可以非常简单地转换串行调用。
- 附加到旋转木马的图像顺序将与缩减数组一致,即 "right order"。
- 任何个人的ajax错误都不会破坏整个企业。
- 不需要中间
promises
数组或 jQuery 的繁琐$.when.apply(null, promises)
(或其他库中更友好的.all()
)。