2015-06-18 7 views
9

Ich implementiere einen Web Map Client, der auf OpenLayers3 aufbaut, der in der Lage sein sollte, sich mit mehreren WMS Servern zu verbinden, nach WMS Capabilities zu fragen und Layer anzuzeigen, die von Servern angekündigt werden.Wie verbinde ich das (bei jeder Funktion)?

var MyMapClient = function(params) { 
    this.wms_sources_ = params.wms_sources; 
    this.wms_capabilities_ = []; 
} 

MyMapClient.prototype.parse_capabilities = function(index) { 
    var capabilities = this.wms_capabilities_[index]; 
    // do something with capabilities 
} 

MyMapClient.prototype.load_wms_capabilities = function() { 
    var parser = new ol.format.WMSCapabilities(); 

    jQuery.each(this.wms_sources_, (function (index, wms_source) { 

     console.log("Parsing " + wms_source.capabilities_url); 

     jQuery.when(jQuery.ajax({ 
      url: wms_source.capabilities_url, 
      type: "GET", 
      crossDomain: true, 
     })).then((function (response, status, jqXHR) { 
      var result = parser.read(response); 
      console.log("Parsed Capabilities, version " + result.version); 
      this.wms_capabilities_[index] = result; 
      return index; 
     }).bind(this)).then(this.parse_capabilities.bind(this)); 

    }).bind(this)); 
}; 

Der obige Code funktioniert gut, aber ich muss bind(this) jedes Mal möchte ich eine Funktion aufrufen, die Zugriff auf „private“ Variablen von MyMapClient ‚s Instanz benötigt. Gibt es keinen besseren Weg, um auf Instanz-Interna konsistent zuzugreifen, ohne die Lesbarkeit zu beeinträchtigen?

Antwort

7

Ich würde sagen, das Beste aus beiden Welten zu verwenden, das heißt, eine lokale Variable den richtigen Rahmen zu halten, und fordert zu bind() wo nötig:

MyMapClient.prototype.load_wms_capabilities = function() { 
    var parser = new ol.format.WMSCapabilities(), 
     _this = this; 

    jQuery.each(this.wms_sources_, function (index, wms_source) { 
     console.log("Parsing " + wms_source.capabilities_url); 

     jQuery.when(jQuery.ajax({ 
      url: wms_source.capabilities_url, 
      type: "GET", 
      crossDomain: true, 
     })).then(function (response, status, jqXHR) { 
      var result = parser.read(response); 
      console.log("Parsed Capabilities, version " + result.version); 
      _this.wms_capabilities_[index] = result; 
      return index; 
     }).then(
      function() { return _this.parse_capabilities(); } 
      // or else 
      // _this.parse_capabilities.bind(_this) 
      // pick the one you like more 
     ); 
    }); 
}; 
+0

Das wird nicht funktionieren: Die Methode 'this' innerhalb der' parse_capabilities' wäre nicht an den Kontext "instance" gebunden, sondern an den Kontext von jQuery (weil jQuery 'parse_capabilities' aufruft.) –

+0

Ich habe diesen Ansatz bereits vorgeschlagen (jetzt gelöscht) - OP sagt, dass er sich dieser Methode bewusst ist (sollte das wahrscheinlich in die Frage bearbeiten), aber wenn möglich vermeiden will, und @deceze hat zu Recht auf "Das hilft dann nicht" (self.parse_capabilities) hingewiesen " –

+0

Bearbeitet, sollte nun funktionieren, weniger" schön "aber ... vielleicht wäre' bind() 'einfach besser. –

1

Sie können „hart binden“ eine Methode wie folgt:

function Foo() { 
    this.bar = this.bar.bind(this); 
} 

Foo.prototype.bar = function() { 
    return console.log(this.baz); 
}; 

Übrigens, das ist, was CoffeeScript kompiliert, wenn dies zu tun:

class Foo 
    bar: => 
    console.log @baz 

Der => Betreiber verursacht diese Erhaltung des Kontextes.

+0

Ich bin immer noch nicht sicher, wie das mit der hilft 'parse_capabilities' Methode für den Prototyp? Ich denke, was auch immer der Fall ist, du müsstest das immer noch in den Aufruf von '.then()' binden? –

+0

Dies funktioniert mit der Methode 'parse_capabilities'. Es kann jedoch nicht auf innere anonyme Funktionen angewendet werden. –

Verwandte Themen