1

ここで奇妙な問題が発生しています。皆さんが助けてくれることを願っています。

プロジェクトの詳細

メソッドを含む大規模なアプリケーションの単純な pub/sub 実装に取り​​組んでいますpubsub.subscribe_once()。このメソッドは、1 回限りのサブスクリプションの作成を有効にします。つまり、ジェネリック サブスクリプションが作成され、適切な「発行」イベントが発生してサブスクリプション コールバックが実行されると、サブスクリプション自体が削除されます。

subscribe_once: function(topic, func) {
    var sub = pubsub.subscribe(topic, func),
        old_func = sub.func;

    // rewrite our subscription's method to remove itself after invocation
    sub.func = function() {
        // call the original function
        old_func.apply(this);
        // remove subscription from topic
        pubsub.unsubscribe(sub);
    };

    return sub;
}

問題

このプロセスのメモリフローに何らかの問題があるようです。(以下の説明を最もよく理解するために、以下の jsfiddle デモを実行することをお勧めします。) subscribe_once('someevent') サブスクリプションを作成してから、publish('someevent') を起動します。publish メソッドが呼び出されたときに期待されることは、トピックのハッシュテーブルに、Subscription オブジェクトの配列を参照する「someevent」キーが含まれていることです。実際、topics["someevent"] を参照すると、単一のサブスクリプションを持つ配列が表示されます。ただし、トピックを参照すると、「someevent」キーが表示されますが、配列は空です!

pubsub.unsubscribe(sub);この関数は を実行するまで起動されないように見えますが、コメントアウトすることで問題は解消されますconsole.log(topics)

さらに、これは特定のブラウザの「スレッド化」の問題ではないようですconsole.log。試しconsole.log(topics, topics[topic], topics, topics[topic])てみると同じ結果が得られます。

デモ: http://jsfiddle.net/4Ab6c/

どんな助けでも歓迎です!ありがとう。

4

1 に答える 1

2

私はまだ私をバックアップするためのいくつかのドキュメントを探していますが、コンソールのオブジェクト表示があなたのtopicsオブジェクトに対して遅延評価を実行しているのではないかと思います。配列にプッシュされた後にメソッドに追加console.log(topics)しましたが、「ここではありません」ログと同じ結果が得られます。フィドルの最後の行をラップして、コールバックが実行される前にオブジェクトツリーを開くと、配列にサブスクリプションが表示され、コールバックが実行された後もその状態が維持されます。コールバックが実行される前にコンソールでオブジェクトツリーを開かないと、空の配列が表示されます。subscribesubpubsub.publish('someevent')setTimeoutpublish

ブログ投稿など、遅延評価が行われていることを確認するものを探し続けます。

十分に明確にしていない場合に備えて、怠惰な意味では、コンソールでツリービューをクリックして開くまで、コンソールはオブジェクトの詳細を収集しません。

私はChromeで働いています。

アップデート

Firefoxでも同様の動作が見られます。Firefoxは、配列に1つのオブジェクトがあることを認識しますが、公開が起動する前に配列にドリルダウンしないと、配列のドリルダウンは空になります。

私はあなたのコメントからフィドルを更新しました:

http://jsfiddle.net/4Ab6c/2/

これを試してください:

  • 公開イベントが発生する前に、フィドルを実行して最初のconsole.logのオブジェクトツリーを展開します。5秒のタイムアウトに設定しましたが、コンソールにアクセスしてクリックする速度に応じて、長くしたり短くしたりできます。インスペクターが開いています。

  • 期待どおりに配列にサブスクライブオブジェクトが表示されます。

  • コンソールをクリアして、フィドルを再度実行します。今回は、publishイベントが発生し、すべてのコードの実行が完了するまで、オブジェクトインスペクターを開かないでください。

  • これで、最初のconsole.logのオブジェクトインスペクターを開いたときに、配列にサブスクリプションイベントが表示されないはずです。

UPDATE 2 これは、同じ動作を示すはるかに単純なフィドルです。

http://jsfiddle.net/4Ab6c/3/

2番目が表示される前に最初に展開すると、foo:barが表示されます。2番目が表示された後に最初に展開すると、foo:bazが表示されます。

更新3

そして、出来上がり、別のSOの質問は、遅延評価の動きを秒単位にします。

于 2012-09-14T21:11:28.937 に答える