2012-12-14 122 views
1

我已經有一個被用作聊天客戶端的SignalR的實現。問題似乎是我有一個客戶端計時器,即ping服務器以通知所有其他客戶端的用戶狀態。SignalR javascript客戶端計時器錘擊連接的服務器

在這種情況下,我有一個心跳和最新活動。心跳每十五秒鐘左右到達一次服務器,最新的活動跟蹤用戶的交互性。這兩個值被傳遞給服務器,以便可以通知所有其他客戶端其他人的狀態。即:如果用戶A沒有移動鼠標超過一分鐘,當他們的心跳擊中服務器時,它將通過SignalR向其他用戶廣播,他們現在'離開'了。

反正我有在SignalR連接似乎呈指數級增長的問題中,連接到聊天應用程序的用戶數量越多。

這是客戶JS計時器的,我懷疑是腥的源代碼,但我不知道爲什麼:

define(['jquery', 'underscore', 'backbone'], 
function ($, _, Backbone) { 

    var Timer = Backbone.Model.extend({ 
     defaults: { 
      interval: 1 * 10 * 1000, 
      timeout: null 
     }, 

     initialize: function (options) { 
      _.bindAll(this, 'start', 'tick', 'stop', 'tickNow'); 
      if (options.interval) { 
       this.set('interval', options.interval); 
      } 
     }, 

     start: function() { 
      var timer = setTimeout(this.tick, this.get('interval')); 
      this.set('timeout', timer); 
     }, 

     tick: function() { 
      var self = this; 
      self.trigger('timerexpired', this); 
      self.start(); 
     }, 

     tickNow: function() { 
      var self = this; 
      self.stop(); 
      self.trigger('timerexpired', this); 
      self.start(); 
     }, 

     stop: function() { 
      clearTimeout(this.get('timeout')); 
     } 
    }); 

    return Timer; 
}); 

回答

2

我注意到你在start timer方法中使用了this關鍵字。這可能是因爲你撥打this.tick的呼叫在實際發生時與上下文無關。嘗試:

start: function() { 
    var self = this; 
    var timer = setTimeout(this.tick, self.get('interval')); 
    this.set('timeout', timer); 
}, 

在瀏覽器中,查克斷點到tick方法,並檢查你確實引用了正確的定時器。

1

我怎麼看不到進展必然是指數,但線性進展肯定會傾向於它。基本上,您可以在這裏執行兩項主要的操作:

  • 在客戶端使用長輪詢/限制,但您已經每隔15秒發送一次請求,以免違反瀏覽器限制。
  • 在服務器端,如果你想要一個大型的Ajax應用程序,你絕對需要一個負載平衡器。在雲中進行亞馬遜自動擴展,這可能會幫助您,並使用負載平衡器。這不會很便宜,而且與您體驗的活動成正比。
+0

感謝您的回答,但限制不是客戶端或服務器端,因爲dev規模最多爲三到四位用戶。我已經將問題縮小到最有可能是上面的計時器 – HCdev

0

你不應該簡單地傳遞this.tick作爲第一個參數來setTimeout,因爲當tick方法被執行this將被綁定到全局window對象,而不是Timer實例。

Timer實例已在運行時,您應該也可能確保不要撥打start。我會改變下列方法,像這樣:

start: function() { 
     var self = this; 
     if (this.get('timeout') !== null) { 
      throw "start must not be called when the Timer is already running"; 
     } 
     // creating a closure ensures this is bound correctly in tick() 
     var timer = setTimeout(function() { 
      self.tick(); 
     }, this.get('interval')); 
     this.set('timeout', timer); 
    }, 

    tick: function() { 
     this.set('timeout', null); 
     this.trigger('timerexpired', this); 
     this.start(); 
    }, 

    stop: function() { 
     clearTimeout(this.get('timeout')); 
     this.set('timeout', null); 
    } 

最顯而易見的方法來檢查計時器是否正常工作是調用CONSOLE.LOG到timerexpired事件綁定,以確保不被觸發事件超出預期。

如果您需要幫助確定併發連接數量失控的原因,您應該將代碼放在停止位置並啓動SignalR連接。

相關問題