簡體   English   中英

flickrapi(js)循環中的多個異步調用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM