I'm implementing a web map client built on top of OpenLayers3 which should be able to connect to multiple WMS servers, ask for WMS Capabilities and show layers advertised by servers.
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));
};
The code above works fine but I have to bind(this)
every time I want to call a function which needs access to "private" variables of MyMapClient
's instance. Isn't there a better way to access instance internals consistently, without sacrificing readability?
Avoid binding by using the public class fields syntax, or bind your callbacks inside the constructor.
Why? Because, arrow functions do not bind their own this, instead, they inherit the one from the parent scope or lexical scope. So, it inherited the value of this from App component and that's why there is not need to explicitly bind it.
First Method: We can use an arrow function in the render method where we are attaching the event handler. There is one performance implication in this method i.e. whenever the component re-renders the function will be created again and again.
bind(something) returns a new function, in which references to this will refer to something . This is a way of saving the current value of this , which is in scope during the call to the constructor, so that it can be used later when the function is called.
I would say to use the best of both worlds, that is, a local variable holding the correct scope, and calls to bind()
where needed:
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
);
});
};
You can "hard bind" a method like this:
function Foo() {
this.bar = this.bar.bind(this);
}
Foo.prototype.bar = function() {
return console.log(this.baz);
};
Incidentally, that's what CoffeeScript compiles to when doing this:
class Foo
bar: =>
console.log @baz
The =>
operator causes this preservation of context.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With