6 Stimmen

Coffeescript-Zeitgeber und "this"-Zeiger bei Rückruf

Ich habe ein Problem damit, was der Browser als "dies" betrachtet. Im folgenden Beispiel wird der Aufruf von pingMe() auf abc 1 Sekunde warten und dann wird der Browser sagen, dass Object DOMWindow keine Methode 'func' hat. Anstatt 'this' auf die Instanz der Klasse ABC (abc) aufzulösen, wird stattdessen das DOMWindow aufgelöst, als ob das Objekt nicht beteiligt wäre. Ich verstehe offensichtlich nicht, wie setTimeout in Bezug auf den Callback-Bereich funktioniert. Irgendwelche Vorschläge, wie ich diesen Callback erfolgreich machen kann?

class ABC
  @func = null

  constructor: (func) ->
    @func = func

  pingMe: ->
    setTimeout(doPing, 1000)

  doPing = ->
    @func()

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

10voto

Reiner Gerecke Punkte 11586

Ich habe diesen Code zum Laufen gebracht.

class ABC
  @func = null

  constructor: (func) ->
    @func = func

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

  doPing: ->
    @func()

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

Ihre doPing-Methode wurde definiert doPing = -> , während die anderen alle name: -> Ich habe es so geändert. pingMe verwendet => um eine unbenannte Funktion zu erstellen, und @doPing zu binden this zur Funktion.

Ich bin mir nicht sicher, ob das richtig ist, denn ich verwende selten JavaScript. Aber ich hoffe, es könnte Ihnen eine Richtung geben, um weiter zu suchen.

1voto

joeytwiddle Punkte 26603

Eine alternative Lösung, die näher an der Vorgehensweise in ES5 liegt, ist:

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

oder wenn Sie sich die Klammern sparen wollen:

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

_Beachten Sie, dass bind ist ES5, also nur verfügbar im IE ab Version 9._


Beachten Sie außerdem, dass Sie auf jeden Fall vermeiden der Versuchung zu widerstehen:

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

denn beide übergeben die Zahl als zweites Argument an bind , nicht setTimeout !

0voto

Leo O'Donnell Punkte 203

Für ein wenig mehr Klarheit können Sie stattdessen die Methode "doPing" binden. Es wird ein bisschen sauberer aussehen und FWIW, ich denke, es besser ausdrückt, was Sie suchen, um zu erreichen.

class ABC
  @func = null

  constructor: (func) ->
    @func = func

  pingMe: ->
    setTimeout => @doPing, 1000

  doPing: =>
    @func()

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X