2017-06-15 70 views
0

我的問題是,如果它有可能限制特定事件的綁定監聽器的可能性?比如我有一個聽衆:是否有可能限制socket.io每個事件只有一個偵聽器?

//In server 
socket.emit('something', { message: 'Hello World!' }); 

//At client 
socket.on('something', (data) => { 
    console.log(data.message); 
}); 

//Output in console 
Hello World! 

但是,如果我複製該段代碼中的其他地方,我綁定2個相同的聽衆一個事件,所以我得到的,我想只有一個2個控制檯日誌。

//In server 
socket.emit('something', { message: 'Hello World!' }); 

//At client 
socket.on('something', (data) => { 
    console.log(data.message); 
}); 

socket.on('something', (data) => { 
    console.log(data.message); 
}); 

//Output in console 
Hello World! 
Hello World! 

我知道有可能具有用於在單個事件不同的動作多個偵聽但是當我在一些框架socket.io使用和框架部件之間進行切換(其中I在部件的構造已經結合)每次在組件之間切換時,都會將相同的偵聽器綁定到相同的事件。所以結果如上所述。

所以我的問題是:

  • 是否可以檢查是否一些事件已經有監聽器,而忽略第二個綁定?
  • 或者,如果它有一些socket.io配置設置,將允許每個事件綁定一個偵聽器,並綁定一個新的,它會覆蓋舊的?
  • 或者只是一些關於如何處理這種情況的良好做法?
+1

停止監聽當您使用更改組件:socket.removeListener(「東西」,東西);更多信息:https://stackoverflow.com/questions/23092624/socket-io-removing-specific-listener –

+0

謝謝你,我已經在angular2中編寫了一個類似於服務的接口,並將它作爲答案發布在這裏,我使用了你的介詞和socket .off函數(就我所知,它與socket.removeListener相同) – BoonZ

回答

1

socket.io套接字源自EventEmitter對象。因此,其監聽器功能完全來自該實現。 EventEmitter對象不具有阻止給定事件的多個偵聽器的功能。

所以,你有幾種選擇:

  1. 您可以刪除第一個事件監聽器時,它就是你不再想它重視。

  2. 您可以覆蓋.on()以拒絕爲已具有處理程序的事件設置新處理程序,或者在設置新處理程序之前刪除之前的處理程序。

  3. 您可以更改自己的邏輯,以便您自己的代碼在您不再希望它活躍時刪除自己的事件偵聽器。

這裏你可以調用每一個新的插座,以避免以往任何時候都具有給定eventName不止一個監聽功能:

function hookSocketSingle(socket) { 
    let origOn = socket.on; 
    socket.on = function(eventName, listener) { 
     // allow the event handler to be registered only if one doesn't already exist 
     if (this.listenerCount(eventName) === 0) { 
      return origOn.call(this, eventName, listener); 
     } else { 
      return this; 
     } 
    } 
} 
0

從「保熱」評論的幫助和「jfriend00」回答我已經解決了Angular2框架和Socket.IO庫的問題。

所以首先我創建了一個服務來保持在整個組件創建和銷燬週期中打開Socket.IO連接。

import { Injectable } from '@angular/core'; 

declare var io: any; 

@Injectable() 
export class SocketService { 

    // We create socket object for socket.io lib and events object 
    // to store all events that are bound from specific component 
    socket; 
    events; 

    // When the service is injected it checks if socket.io and our 
    // events objects are initialised 
    constructor() { 
     if(!this.socket) { 
      this.socket = io(environment.apiURL); 
      this.events = {}; 
     } 
    } 

    // Then we create a middleware function to intercept the socket.on() 
    // function and we request one more parameter which is the component name. 
    on(component, event, callback) { 
     // We check if component key already exists in our events object. 
     if(this.events[component]) { 
      // We check if the wanted event is already bound in selected component 
      // (basically we check if its added to events[component] array) 
      if(this.events[component].indexOf(event) < 1) { 
       // If it's not added we bind the event to socket and add it to events[component] array 
       this.events[component].push(event); 
       this.socket.on(event, callback); 
      } 
     // If the component key does not exist we initialise event[component] as an array 
     // and we add our event to the array as well as we bind the socket event 
     } else { 
      this.events[component] = []; 
      this.events[component].push(event); 
      this.socket.on(event, callback); 
     } 
    } 

    // We also create a middleware function to intercept the socket.emit() 
    // function and just forward data to socket.emit 
    emit(event, data = {}) { 
     this.socket.emit(event, data); 
    } 

    // And last we add unsubscribe function so we can unbind all listeners from 
    // single component (mostly used in onNgDestroy() when we don't want that bound events 
    // are persistent between more than one component) 
    unsubscribe(component) { 
     // We check if component key exists in events object 
     if(this.events[component]) { 
      // We iterate through array and we remove listeners for every 
      // event that was bound to selected component 
      this.events[component].forEach((event) => { 
       this.socket.off(event); 
      }); 

      // And in the end we remove component key from events 
      delete this.events[component]; 
     } 
    } 
} 

因此,我們必須對我們可以綁定許多事件,我們希望,他們是由組件進行排序,所以我們知道哪些成分具有綁定服務。如果我們想要在同一個組件中綁定相同的事件,我們只是忽略它,當我們想要的時候,我們可以解除組件中的所有內容,這樣當組件被銷燬或不活動時,就不會觸發一些有趣的動作。

在組件方面,我們使用像所有其他服務:

import { ApiService } from '../core/socket.service'; 

@Component({ 
    templateUrl: './example.component.html', 
    styleUrls: ['./example.component.scss'] 
}) 
export class ExampleComponent { 

    // We inject our socket service in constructor 
    constructor(private socket: SocketService) { 
     // We bind wanted events with component name and handle them as we would normally in socket.io 
     this.socket.on(this.constructor.name, 'event1', (data) => { 
      console.log(data); 
     }); 

     this.socket.on(this.constructor.name, 'event2', (data) => { 
      console.log(data); 
     }); 
    } 

    ... other functions ... 

    // If we don't want to keep our events persistent for another component we just unsubscribe. 
    // When we will return to this component it will re-bind the events stated in component constructor. 
    // But if we choose to use persistent mode it will not duplicate the events. 
    ngOnDestroy() { 
     this.socket.unsubscribe(this.constructor.name); 
    } 
} 
+0

是否應該從你問的問題中獲得所有這些?看起來我的回答似乎回答了你問的問題,你在這裏展示的東西與提出的實際問題無關,而是建立在我在答案中解釋的概念之上。我知道這是你試圖解決的問題的總體,但其中大部分似乎與你提出的問題沒有任何關係。有點驚訝,我猜這是公認的答案。 – jfriend00

+0

當你從他們的答案中提取概念時,並不真正鼓勵人們提供答案,將它與許多與你在問題中提問無關的東西結合起來,然後接受你自己的答案。 – jfriend00

+0

Sry,我已經改變了你接受的答案,但是因爲我想分享我的最終結論,它確實解決了我的問題:D(確實使用你的概念),但是當我提出一個問題時,我試圖將其作爲抽象因爲我可以這樣做,因爲更多的人可以回答它。所以它很難在抽象問題上得到概念上的答案。真誠的 – BoonZ

相關問題