我几乎把头撞到了墙上,因为我无法得到以下代码。我正在尝试使用flickrApi对照片库进行编码,并且遇到多个异步调用的问题。但也许有一个更清洁的解决方案来编码。
单击photoset的链接时会调用openPhotoset()。不幸的是,获取照片的描述我需要使用不同的方法,这意味着另一个异步调用。我正在遍历数据,但因为我在一个循环中进行调用(当我有照片ID可用时),openPhotoset()的延迟在循环之后但之前没有解决。我阅读并看过在循环中使用$ .when()的示例,使用deferreds填充数组并使用$ .when进行检查但是我似乎对它失败了。这是我需要的解决方案还是有另一条救赎之路? ;)我想在openPhotoset()中的所有调用完成后执行不同的函数。
function openPhotoset(photosetId) {
var currentPhotoset = [],
deferred = $.Deferred();
_requestPhotosOfSet(photosetId).done(function(data){
$(data.photoset.photo).each(function(i, photo){
var objPhoto = {};
objPhoto.id = photo.id;
objPhoto.title = photo.title;
objPhoto.farm = photo.farm;
objPhoto.server = photo.server;
objPhoto.secret = photo.secret;
// get photo description
requestPhotoInfo(photo.id).done(function(data) {
objPhoto.description = data.photo.description._content;
currentPhotoset.push(objPhoto);
}).then(function() {
// TODO: renders with each iteration, shouldnt!
var template = $('#li-gallery').html(),
result = Mustache.render(template, {currentPhotoset:currentPhotoset});
showGallery();
_$fyGallery.find('.gallery-list').html(result);
deferred.resolve();
});
});
});
return deferred;
}
答案 0 :(得分:1)
你可以通过在几个地方更改.done()
.then()
并重新安排一些事情来做到这一点 - 相当不错
很多。
我想你可能一直在寻找这样的东西:
function openPhotoset(photosetId) {
return _requestPhotosOfSet(photosetId).then(function(data) {
var promises = $(data.photoset.photo).map(function(photo) {
return requestPhotoInfo(photo.id).then(function(data) {
return {
id: photo.id,
title: photo.title,
farm: photo.farm,
server: photo.server,
secret: photo.secret,
description: data.photo.description._content
};
});
}).get();//.get() is necessary to convert a jQuery object to a regular js array.
return $.when.apply(null, promises).then(function() {
var template = $('#li-gallery').html(),
result = Mustache.render(template, {
currentPhotoset: Array.prototype.slice.apply(arguments)
});
showGallery();
_$fyGallery.find('.gallery-list').html(result);
});
});
}
这里的主要区别是创建一个promises数组而不是一个照片对象数组,并允许promises传递数据。这允许$.when()
在满足所有承诺时启动回调 - 即,当为集合中的所有照片组成数据对象时。
请注意使用.map()
代替.each()
,从而简化promises
的创建。
最后,openPhotoset()
返回的整体承诺允许在完成整个过程时采取任何行动。只需链.then()
。
openPhotoset(...).then(function() {
// here, do whatever
});
修改强>
如果内部工作被拉出并重新定义为命名的承诺返回函数 - getPhotoInfoObject()
和renderData()
,则整体模式可能更容易理解。
function openPhotoset(photosetId) {
function getPhotoInfoObject(photo) {
return requestPhotoInfo(photo.id).then(function(data) {
//$.extend() is much less verbose than copying `photo`'s properties into a new object longhand.
return $.extend(photo, {description: data.photo.description._content});
});
}
function renderData() {
var template = $('#li-gallery').html(),
currentPhotoset = Array.prototype.slice.apply(arguments),
result = Mustache.render(template, {
currentPhotoset: currentPhotoset
});
showGallery();
_$fyGallery.find('.gallery-list').html(result);
}
// With the inner workings pulled out as getPhotoInfoObject() and renderData(),
// the residual pattern is very concise and easier to understand.
return _requestPhotosOfSet(photosetId).then(function(data) {
var promises = $(data.photoset.photo).map(getPhotoInfoObject).get();
return $.when.apply(null, promises).then(renderData);
});
}
答案 1 :(得分:0)
我被deferreds和$ .when函数所蒙蔽,我没有注意到我需要的只是创建一个计数器并在每次requestPhotoInfo完成后倒计时并在渲染html之后