1

私は Spotify アプリを持っていて、ループが終了するのを待ちたいと思っています。ただし、アプリを一度リロードした後にのみ機能します。

function matchRecommendations(result) {
var deferreds = new Array();
for ( var i = 0; i < result.length; i++) {
    // Async wait
    var dfd = $.Deferred();
    deferreds.push(dfd.promise());

    ...

    // Wait for search to finish
    search.tracks.snapshot(0, 1).done(
            function(snapshot) {
                // If match was found => create recommendation object
                var uri = snapshot._uris[0];
                var meta = snapshot._meta[0];
                if ($.type(meta) !== "undefined") {
                    if ($.type(meta.name) === "string") {
                        console.log(uri);
                        var rec = new Recommendation(uri, meta,
                                explanation, score);
                        RadioView.prototype.addRecommendation(rec);
                    }
                }

                // Async task finished
                dfd.resolve();
            });
}

return deferreds;
} 

ここでは、上記のメソッドを呼び出しており、それが終了するのを待ちたいと考えています。

 $.when.apply($, matchRecommendations(result)).done(
                            function() {
                                console.log("finished");
                                RadioView.prototype.render();
                            });

なぜこれが機能しないのか、問題がわかりません。問題は、初回ロード時に「完了」コールバックが実行されないことです。アプリをリロードすると問題なく動作します...Deferred Stuff に何か問題がありますか?

4

2 に答える 2

0

これは確かに、古くからおなじみのスコープの問題です。スコープ内にはスコープが 1 つしかなくmatchRecommendations()、ループ内に設定されたすべての var はforそれぞれ最終値を持ち、ループが終了すると他にはありません。

これにはいくつかの方法がありますが、最も簡単なのは (すでに jQuery を使用しているため) でresult配列をループすることjQuery.each()です。

コードは次のようになります。

function matchRecommendations(result) {
    var promises = [];
    $.each(result, function(i, rslt) {
        ...
        var p = search.tracks.snapshot(0, 1).done(function(snapshot) {
            var uri = snapshot._uris[0];
            var meta = snapshot._meta[0];
            if ($.type(meta) !== "undefined" && $.type(meta.name) === "string") {
                console.log(uri);
                RadioView.prototype.addRecommendation(new Recommendation(uri, meta, explanation, score));
            }
        });
        promises.push(p);
    });
    return promises;
} 

ノート:

  • @adeneo が指摘するようにsearch.tracks.snapshot()、promise を返します (少なくとも、そうであると想定しても安全だと思われます)。そのため、カスケードで解決されるセカンダリ Deferred を作成する必要はありません。
  • for(Doh!) 2 番目の Deferred がなければ、スコープの問題は実際にはなくなるので、必要に応じてループに戻ることができます。
于 2013-04-08T00:36:11.793 に答える