0

これはすでに尋ねられていることは確かですが、何を検索すればよいかわかりません。ともかく、

var livemarks = [];

var livemarkIds = PlacesUtils.annotations.getItemsWithAnnotation("livemark/feedURI", {});

for (var i = 0; i < livemarkIds.length; i++){

    PlacesUtils.livemarks.getLivemark( {id : livemarkIds[i]}, function(result, livemark){

        if (result == Components.results.NS_OK){
            livemarks.push(livemark);
        }

    });

}

alert(livemarks.length);

少し学ぶために、作成者が管理しなくなったFirefoxアドオンを少し試してみました。最近、getFeedURIが非推奨になり、彼の古い関数を変更したいというエラーが発生しました。

編集:

関数で定義された関数(内部関数)から、親で定義された変数にアクセスできません。なんで?たとえば、getLivemark()または他の同様の内部関数の内部からvarlivemarksにアクセスできません。

私はチェックしていました(完全にスクロールダウン):これと彼のコードは正常に機能します。では、私のコードの何が問題になっていますか?可能であれば、再帰を避けたかっただけです。

4

1 に答える 1

6

関数は非同期PlacesUtils.livemarks.getLivemarkで機能していると思われるので、アラートを出した後にコールバックが呼び出されます。コールバック内にアラートを配置すると、正しい長さが表示されます(最終的に)。これが1つの方法です:length

var expecting = livemarkIds.length;
for (var i = 0; i < livemarkIds.length; i++){

    PlacesUtils.livemarks.getLivemark( {id : livemarkIds[i]}, function(result, livemark){

        if (result == Components.results.NS_OK){
            livemarks.push(livemark);

            // ***New stuff***
            if (livemarks.length === expecting) {
                // Now you have them all, now you can do the next thing
                doSomethingWithTheLiveMarks(livemarks);
            }
        }

    });
}

関数の実行中に他のことを行う場合に備えて、ここに入れていることに注意してくださいlivemarkIds.length。そうでない場合は、それを直接使用できます。expectinglivemarkIds


以下のコメントを再確認してください。

ただし、システムは次のように機能します。配列でライブマークを取得します。このコードは実際にはクラス(およびメソッド)にあるため、別のクラスがこのコードを初期化し、関数getFeeds()を呼び出します。この関数は、ライブマークの配列を返します。

PlacesUtils.livemarks.getLivemarkが非同期の場合、配列を戻り値として返すことはできません。たとえば、次のように使用することはできません。getFeeds

a = b;
c = 42;
feeds = getFeeds(feedIds);
if (feeds.length === 0) {
    // Do something
}
else {
    // Do something else
}

良いニュースは、修正が非常に簡単なことgetFeedsです。フィードがあるときに呼び出すコールバック関数を受け入れてください。上記のコードは次のように変更されます。

a = b;
c = 42;
feeds = getFeeds(feedIds, function(feeds) {
    if (feeds.length === 0) {
        // Do something
    }
    else {
        // Do something else
    }
});

ご覧のとおり、これは非常に簡単な変更です。上記のループがすべてであると仮定するとgetFeeds、次のgetFeedsようになります。

function getFeeds(livemarkIds, callback) {

    var livemarks = [];
    for (var i = 0; i < livemarkIds.length; i++){

        PlacesUtils.livemarks.getLivemark( {id : livemarkIds[i]}, function(result, livemark){

            if (result == Components.results.NS_OK){
                livemarks.push(livemark);

                if (livemarks.length === livemarkIds.length) {
                    // Done, trigger the callback
                    callback(livemarks);
                }
            }

        });
    }
}

そしてパターンは続きます:コード呼び出しgetFeedsが非同期のものからの戻り値を期待している他の何かによって呼び出されている場合、その値を返す代わりに、そのコードにコールバックを受け入れさせ、コールバックからコールバックを呼び出しgetFeedsます。等々。

慣れれば、とても簡単です。それに慣れるのは難しいかもしれません。:-)

于 2012-06-21T17:37:25.230 に答える