2011-02-07 9 views
6

Tengo un problema con lo que el navegador considera 'esto'. En el siguiente ejemplo, al llamar a pingMe() en abc esperará 1 segundo y luego el navegador dirá que Object DOMWindow no tiene el método 'func'. En lugar de resolver 'this' con la instancia de la clase ABC (abc), en su lugar se resuelve en DOMWindow, como si el objeto no estuviera involucrado. Claramente no entiendo cómo funciona setTimeout con respecto al alcance de devolución de llamada. ¿Alguna sugerencia de cómo puedo hacer que esta devolución de llamada tenga éxito?Coffeescript timer y 'this' puntero en callback

class ABC 
    @func = null 

    constructor: (func) -> 
    @func = func 

    pingMe: -> 
    setTimeout(doPing, 1000) 

    doPing = -> 
    @func() 

abc = new ABC -> 
    alert "HI" 
abc.pingMe() 
+1

hm, cambiando la línea setTimeout a 'obj = this; setTimeout ((-> obj.doPing()), 1000) 'y la declaración doPing a' doPing: -> 'parece arreglarlo. Parece que CoffeeScript mantiene un comportamiento de JavaScript regular en estos escenarios. – Larry

Respuesta

10

Tengo este código funcionando.

class ABC 
    @func = null 

    constructor: (func) -> 
    @func = func 

    pingMe: -> 
    setTimeout => 
    @doPing() 
    , 1000 

    doPing: -> 
    @func() 

abc = new ABC -> 
    alert "HI" 
abc.pingMe() 

Su método de dopaje se define doPing = ->, mientras que todos los otros utilizan name: ->, he cambiado de esa manera. pingMe usa => para crear una función sin nombre, y @doPing para enlazar this a la función.

No estoy seguro si esto es correcto, rara vez uso JavaScript. Pero espero que te pueda dar una dirección para mirar más allá.

+0

sí, eso es todo. mi conocimiento de '=>' faltaba. – Larry

0

Quizás para un poco más de claridad, puede enlazar el método "doPing" en su lugar. Se verá un poco más limpio y FWIW, creo que expresa mejor lo que estás buscando lograr.

class ABC 
    @func = null 

    constructor: (func) -> 
    @func = func 

    pingMe: -> 
    setTimeout => @doPing, 1000 

    doPing: => 
    @func() 

abc = new ABC -> 
    alert "HI" 
abc.pingMe() 
+0

Creo que debería ser '=> @doPing()'. '=> @ doPing' se evalúa como una función que devuelve la función enlazada, no como una función que llama a la función enlazada. Ver la respuesta de Reiner. – joeytwiddle

1

Una solución alternativa que está más cerca de lo que haría en ES5 es:

pingMe: -> 
    setTimeout(@doPing.bind(@), 1000) 

o si usted quiere ahorrar en paréntesis:

pingMe: -> 
    setTimeout (@doPing.bind @), 1000 

Tenga en cuenta que bind es ES5, entonces solo available en IE desde la versión 9.


También tenga en cuenta, que debe a toda costa evitar la tentación de probar:

setTimeout(@doPing.bind @, 1000) # BAD! 
     or 
    setTimeout @doPing.bind @, 1000  # BAD! 

porque ambas cosas pasar el número como el segundo argumento a bind, no setTimeout!