[英]flickrapi (js) multiple async calls in a loop
我全力以赴,因為我無法使以下代碼正常工作。 我正在嘗試使用flickrApi編寫一個照相館,並遇到多個異步調用的問題。 但是也許有一個更干凈的解決方案對此進行編碼。
單擊照片集的鏈接時,將調用openPhotoset()。 不幸的是,獲得照片的描述后,我需要使用其他方法,這意味着需要進行另一個異步調用。 我正在遍歷數據,但是因為我是在循環中進行調用(那是在我有可用的photo-id的情況下),所以openPhotoset()的延遲在循環之后但在解析之前無法解析。 我閱讀並看到了在循環中使用$ .when()的示例,用延遲填充了數組,並用$ .when檢查,但是我似乎在這方面失敗了。 這是我需要的解決方案,還是另辟road徑? ;)
我想在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;
}
您可以通過在幾個地方將.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);
});
});
}
這里的主要區別是創建了一個承諾數組,而不是一個照片對象數組,並允許這些承諾傳達數據。 當所有的諾言都得到滿足時,即當為集合中的所有照片組成數據對象時,這允許$.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);
});
}
我對延遲和$ .when函數視而不見,以至於我沒有注意到我需要做的就是創建一個計數器,並在每次requestPhotoInfo完成后以及在呈現html之后倒計數
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.