0

の配列項目(機能)を取得する方法(https://davidwalsh.name/pubsub-javascriptから抽出):ES6 - 次のようにES6を使用して、パブリッシュ・サブスクライブパターンを考えると、特定のコンテキスト

class PubSub { 
    constructor() { 
     this.handlers = []; 
    } 

    subscribe(event, handler, context) { 
     if (typeof context === 'undefined') { 
      context = handler; 
     } 
     { 
      if (this.getHandler(event, handler) == null) { 
       this.handlers.push({event: event, handler: handler.bind(context), key: Guid()}); 
      } 
     } 
    } 

    unsubscribe(event, handler) { 
     let filteredHandler = this.getHandler(event, handler); 
     if (filteredHandler != null) { 
      let idx = this.handlers.indexOf(filteredHandler); 
      if (idx > -1) { 
       this.handlers.splice(idx, 1); 
      } 
     } 
    } 

    publish(event, args) { 
     this.handlers.forEach(topic => { 
      if (topic.event === event) { 
       topic.handler(args) 
      } 
     }) 
    } 

    getHandler(event, handler) { 
     if (this.handlers == null || this.handlers.length < 1) { 
      return null; 
     } 

     let filtered = null; 

     this.handlers.forEach(topic => { 
      if (topic.event === event && topic.handler === handler) { 
       filtered = topic; 
      } 
     }); 

     return filtered; 
    } 

    getNumOfSubsribers() { 
     if (this.handlers != null && this.handlers.length > 0) { 
      return this.handlers.length; 
     } 

     return 0; 
    } 
} 

購読およびパブリッシュ方法が働きます。ただし、getHandlerおよびunsubscribeメソッドは期待通りに機能しません(getHandlerはnullを返すようです)。私は検索しようとしましたが、この問題(満足している解決策を得ることができませんでした(特定のコンテキストにバインドされた関数がどのように配列から除外されるかは不明です)。

私はコードで何が間違っていますか?親切にgetHandlerについて私に助言し、コードの一部を退会してください。

何か助けてください。

+0

あなたが購読した後、「ハンドラー」は何になるのですか?空かヌルですか?それが空であれば、何かがサブスクリプションコードに間違っているか、サブスクリプションコードに間違ったものが与えられています。ハンドラがnullでない場合、getハンドラコードに何か問題があります。または、元のサブスクリプションで何か問題が発生し、コードがハンドラを見つけられなくなります(nullイベントを送信する場合など)。 –

+0

返されたハンドラがnullであることが判明しました。私は、正しいコンテキストにバインドされた正しいハンドラを取得することを期待していました。この結果で、私はunsubscribeメソッドで指定されたハンドラリストから削除したかったのです。 – oatcrunch

答えて

2

このコードはいくつかの点で奇妙です。

理由がgetHandlerではありません。handlersにプッシュされたオブジェクトのhandlerプロパティが渡された関数ではありません。それはその関数にbindを呼び出した結果です。適切にフォーマットされ、これはsubscribe次のとおりです。

subscribe(event, handler, context) { 
    if (typeof context === 'undefined') { 
     context = handler; 
    } 
    { 
     if (this.getHandler(event, handler) == null) { 
      this.handlers.push({ 
       event: event, 
       handler: handler.bind(context), // ** NOTE ** 
       key: Guid() 
      }); 
     } 
    } 
} 

値が定義により、オリジナルと同じになることはありませんこと。

代わりに、元のハンドラも含めて、後でそれを確認する必要があります。のも無意味スタンドアロンのブロックを取り除くしてみましょう:

subscribe(event, handler, context) { 
    if (typeof context === 'undefined') { 
     context = handler; 
    } 
    if (this.getHandler(event, handler) == null) { 
     this.handlers.push({ 
      event: event, 
      handler: handler.bind(context), 
      originalHandler: handler,  // *** 
      key: Guid() 
     }); 
    } 
} 

さて、getHandleroriginalHandlerとの一致を探すことができます。私たちがそこにいる間、我々はハンドラを見つけたときに、ループではなく、行く維持を停止させ、そして使用意味的に適切なArray#find

getHandler(event, handler) { 
    if (this.handlers == null || this.handlers.length < 1) { 
     return null; 
    } 

    let filtered = this.handlers.find(topic => topic.event === event && topic.originalHandler === handler); 
    return filtered; 
} 

へのハンドラを結合のようなコードを使用して他の問題は、(存在しますcontextが提供されていない場合はそれ自身)、完全なコードレビューは範囲外です。上記の理由でgetHandlerが動作しないため、なぜunsubscribeが機能しません。その修正では、unsubscribeも動作するはずです(ただし、2回検索するのは奇妙です)。

+0

迅速な対応をありがとう。私のコードですばやく試しましたが、それは動作します。簡単な質問ですが、あなたの例のoriginalHandlerは異なるコンテキストで正しく動作しますか?例えば、serviceA.jsとserviceB.jsを持っていて、同じイベント名を登録していて、両方ともそれぞれのコンテキストにバインドされているハンドラと同じ関数名を持っている場合です。 – oatcrunch

+0

@oatcrunch:関数の*名前*は関係ありません。 'getHandler'は*特定の関数*を持つエントリを探すことによって動作します。 (関数はオブジェクトなので、 '=='と '==='は同じ関数を参照する2つの引数/変数を比較する場合にのみ真となります)。 –

関連する問題