2012-05-09 3 views
3

Я начал писать coffeescript на прошлой неделе, так как я программирую новый сайт Play20, где coffeescript является стандартом. Я хочу обновить функцию getData в моем классе каждые 5 минут, но функция setInterval не привязывается к моему классу. Только в первый раз, когда он вызывает getData, потому что объект «this» все еще доступен, поскольку функция setUpdateInterval() вызывается из конструктора.Coffeescript setInterval в классе

Но после первого вызова setInterval больше не имеет никакого соединения с экземпляром Widget и не знает, что такое функция this.getData() (и как его достичь).

Кто-нибудь знает, как это сделать?

Вот мой код:

class Widget 
    constructor: (@name) -> 
    this.setUpdateInterval() 

    getData: -> 
    console.log "get Data by Ajax" 

    setUpdateInterval: (widget) -> 
    setInterval(this.getData(), 3000000) 

ответ

5

Теперь здесь требуется магия Javascript. Reference

class Widget 
    constructor: (@name) -> 
    this.setUpdateInterval() 

    getData: -> 
    console.log "get Data by Ajax" 

    setUpdateInterval: (widget) -> 
    callback = @getData.bind(this) 
    setInterval(callback, 3000000) 

Это будет работать почти во всех браузерах (догадаться, один нет), поэтому функция должны быть связаны по-разному. Некоторая кофейная магия:

callback = => @getData 
+0

вы можете сделать привязку вызова, как 'центибар = @ getData.bind @', и вы также не нужны скобки на 'setInterval' линии ... подробнее кофе. +1, мне может понравиться этот ответ лучше моего, за исключением того, что он не будет работать в IE. – hvgotcodes

+0

Спасибо, код делает именно то, что я хотел сделать (в Chrome)! Одна вещь «callback = -> that.getData.call (that)», похоже, не компилируется. Следующий вопрос, ограничивая различие, вы имеете в виду, что мне нужны два привязки, один для всех браузеров, кроме IE и один специальный для IE, или мне нужно только последнее связывание? – Jacob

+0

@ пользователь1353536 компилируется здесь. – Reactormonk

3

Проблема заключается в том, что вы выполняете функцию, вместо того, чтобы передать ссылку на него.

Теперь, похоже, вам нужно также сохранить область экземпляра. do и => могут помочь с этим.

setUpdateInterval: (widget) -> 
    setInterval (do => 
     @getData), 3000000 
    true 

компилирует

Widget.prototype.setUpdateInterval = function(widget) { 
     var _this = this; 
     setInterval((function() { 
     return _this.getData; 
     })(), 3000000); 
     return true; 
    }; 

вы отметите код выполняет функцию самостоятельной вызывающую, которая возвращает функцию, которая создает замыкание вокруг this, запирая его в область обратного вызова (как _this)

Также обратите внимание, что вам не нужно пропускать виджет в метод (вы его нигде не используете), и вы должны вызвать эту функцию в своем конструкторе для установки интервала. Что бы вы ни делали, вы хотите только один раз вызвать этот метод. Вы можете просто поместить содержимое функции в свой конструктор.

Наконец, поскольку coffeescript возвращает значение последнего оператора из всех функций, я бросаю там true, но это может быть необязательно.

0

Это удобно и в узле. Это вопрос ответа Тасса.

class Widget 
    constructor: (@options = {}) -> 
    @options.interval ?= 1000 
    @setInterval() 

    timer: -> 
    console.log 'do something' 

    setInterval: -> 
    cb = @timer.bind @ 
    setInterval cb, @options.interval 

w = new Widget() 
Смежные вопросы