2014-02-24 155 views
4

我正在創建一個Meteor應用程序,它有一些簡單的計時器。按下定時器上的開始或停止按鈕,每個調用一種方法來設置或清除間隔定時器等等。當我setInterval時,我將結果對象存儲在當前的定時器文檔中,以便稍後當我想要清除間隔計時器時很容易找到。這是我遇到問題的地方。服務器端setInterval/clearInterval與流星

當運行Meteor.setInterval()服務器端時,它返回一個對象。根據node.js文檔,這是正常的。如果我日誌創建後生成的對象,它返回:

{ _idleTimeout: 5000, 
    _idlePrev: 
    { _idleNext: [Circular], 
    _idlePrev: 
     { _idleTimeout: 5000, 
     _idlePrev: [Object], 
     _idleNext: [Circular], 
     _idleStart: 1393271941639, 
     _onTimeout: [Function], 
     _repeat: false }, 
    msecs: 5000, 
    ontimeout: [Function: listOnTimeout] }, 
    _idleNext: 
    { _idleTimeout: 5000, 
    _idlePrev: [Circular], 
    _idleNext: 
     { _idleTimeout: 5000, 
     _idlePrev: [Circular], 
     _idleNext: [Object], 
     _idleStart: 1393271941639, 
     _onTimeout: [Function], 
     _repeat: false }, 
    _idleStart: 1393271941639, 
    _onTimeout: [Function], 
    _repeat: false }, 
    _idleStart: 1393271943127, 
    _onTimeout: [Function: wrapper], 
    _repeat: true } 

如果我從我的文檔檢索它後登錄的對象,我得到這個:

{ _idleTimeout: 5000, 
    _idlePrev: null, 
    _idleNext: null, 
    _idleStart: 1393271968144, 
    _repeat: true } 

因此,使用clearInterval與此不不行。這裏是我的服務器端代碼:

Meteor.methods({ 

    play: function(entry){ //entry is the document 
     var currentPlayTimer = entry; //Global variable for the interval timer 
     Entries.update({_id: currentPlayTimer._id},{$set:{playing:true}}); //This is mostly to set the status of the play button for the client 
     var IntervalId = Meteor.setInterval(function(){Entries.update({_id: currentPlayTimer._id},{$inc:{time:1},$set:{intervalId: IntervalId}});},5000); //Increment by 1 every 5 seconds, put the object from the interval timer into the current document 
     console.log(IntervalId); 
    }, 

    stop: function(entry){ //entry is the document 
     var currentPlayTimer = entry; 
     IntervalId = currentPlayTimer.intervalId; 
     console.log(IntervalId); 
     Meteor.clearInterval(IntervalId); 
     Entries.update({_id: currentPlayTimer._id},{$set:{playing:false, intervalId: null}}); 

    } 
}); 

而且,你會發現,在劇中方法,我設置intervalIdsetInterval函數內。我在絕望中嘗試了這一點,並且工作。出於某種原因,如果我嘗試在創建間隔計時器Entries.update({_id: currentPlayTimer._id},{$set:{intervalId: IntervalId}})後立即更新文檔,則會失敗。

所有這些工作都非常適合客戶端代碼,但我需要在服務器端完成此操作。我希望計時器能夠保持正確的速度,無論您的網頁是在5臺設備上打開還是不打開。

感謝您的幫助!這個項目是我第一次使用Meteor或Node上的任何東西,到目前爲止我非常喜歡它。

回答

6

這本質上是下降到兩個問題:首先,中setIntervalclearInterval的實現是客戶端(至少在鉻)上的不同和節點,其次是you can't serialise functions in BSON,這意味着所有的方法是,和屬性包含方法,當您嘗試將其作爲文檔插入服務器時,將從對象中刪除。這就是爲什麼你隨後檢索的對象變得更簡單/更小,以及爲什麼你不能將它傳遞給clearInterval,因爲它缺少大部分所需的信息。

如果您在客戶端中記錄返回值setInterval,您會注意到它只是一個整數,當然這個整數可以被序列化,所以您可以像MongoDB一樣從MongoDB中獲得完全相同的結果,和clearInterval工作正常。我在set...clearInterval的客戶端實現方面並不是專家,但坦率地說,一個四位數的整數對於這個目的看起來並不特別有效,儘管它確實有一些你已經確定的優點。

總的來說,我認爲你不可能在服務器上嘗試你想要的事情,除非別人能想到一個聰明的方式來串行化部分interval清除它並重建適當對象一旦被檢索到的對象,但這需要更多的Node知識。否則,我認爲你有兩種選擇:

  • 只需將你的區間存儲在某種香草javascript對象的內存中。
  • 使用替代對象進行計時,這將允許您存儲可序列化的標識符。過去我已經使用了meteor-cron軟件包,雖然簡單一些,可能值得一看,看看是否可以使用該軟件包或其衍生產品。
+2

謝謝!這就說得通了。這是我爲此問題的任何其他人所做的: 創建一個數組以保存'setInterval'對象 'var intervalArray = [];' 將對象('IntervalId')推入數組中,存儲位置。這只是一個數字,所以我可以將它存儲在MongoDB文檔中。 'intervalArrayPosition = intervalArray.push(IntervalId) - 1;' 後來,讀的位置退了出來,並明確如下: 'Meteor.clearInterval(intervalArray [intervalArrayPosition]);' – dotbat

+0

我想要做類似的事情,即使用戶關閉了瀏覽器,服務器上的「setInterval」也應該保持運行,直到他們登錄並停止它爲止 - 因此,與想要保存到數據庫相同的問題。註銷後'var intervalArray = []'如何保持? – evolross