TelluIoT / ThingML

The ThingML modelling language
https://github.com/TelluIoT/ThingML
Apache License 2.0
104 stars 32 forks source link

Cannot access "this.propertyListener['ble'] " #151

Closed sdalgard closed 7 years ago

sdalgard commented 7 years ago

I am generating code from ThingML to JS and running on EDISON. This error occurs when executing main.js

`root@ubilinux:~/homemnt/heads/thingml-gen/nodejs/FieldNode/lib# root@ubilinux:~/homemnt/heads/thingml-gen/nodejs/FieldNode/lib# node main.js Filter ReadyDecoder ReadyFilter ReadyComparator ReadyFilter ReadystateChange /root/homemnt/heads/thingml-gen/nodejs/FieldNode/lib/BLE.js:60 if (this.propertyListener['ble'] !== undefined) { ^

TypeError: Cannot read property 'ble' of undefined at Noble. (/root/homemnt/heads/thingml-gen/nodejs/FieldNode/lib/BLE.js:60:26) at emitOne (events.js:90:13) at Noble.emit (events.js:182:7) at Noble.onStateChange (/root/homemnt/heads/node_modules/noble/lib/noble.js:60:8) at emitOne (events.js:90:13) at emit (events.js:182:7) at NobleBindings.onStateChange (/root/homemnt/heads/node_modules/noble/lib/hci-socket/bindings.js:126:8) at emitOne (events.js:95:20) at emit (events.js:182:7) at Hci.processCmdCompleteEvent (/root/homemnt/heads/node_modules/noble/lib/hci-socket/hci.js:588:10) root@ubilinux:~/homemnt/heads/thingml-gen/nodejs/FieldNode/lib# `

sdalgard commented 7 years ago

Files sent in email

brice-morin commented 7 years ago

functions that you pass in callbacks (typically in xxx.on('event', function(params) {})) should be bound to this.

try:

`xxx.on('event', function() {
    }.bind(this, params)
);
jakhog commented 7 years ago

Another way to get around it is to use the fancy new JavaScript Arrow functions, that doesn't bind this to anything new. The code from @brice-morin above, could be written as:

xxx.on('event', () => {
    // this will be the same as outside the callback
});

Or, just don't use this in callbacks. Since it can be quite easily manipulated, it's sometimes hard to know what object it actually points to when the function is called.

Judging by the snippets of code above, this could be done e.g. like this:

var that = this;
xxx.on('event', function() {
    // use that instead of this
    that.propertyListener['ble'] ...
});

or for the errors @sdalgard posted, maybe

var propertyListener = this.propertyListener;
xxx.on('event', function() {
    propertyListener['ble'] ...
});
maxleiko commented 7 years ago

Another good reason not to use function binding, is performance.
.bind(...) creates a brand new function which is bound to a context, and this is time consuming, so you should not use it if you are in a loop or something "time-critical".

brice-morin commented 7 years ago

Right. So I guess the recommended way is the first one proposed by Jakob. The problem is not really a ThingML problem (though we could surely remove some bind here and there) but more a problem when mixing JS with ThingML.

sdalgard commented 7 years ago

I agree the arrow function seems to be a promising option. It seems it is supported from node.js v5.11 (with some bugs) according to http://node.green/ Noble seems to support up to node.js v5.5 (according to .travis.yml) An issue about supported node.js versions is filed (https://github.com/sandeepmistry/noble/issues/540) Time will show...

sdalgard commented 7 years ago

Noble v1.7.0 + Node.js v5.5.0 works well with arrow functions. Case solved :-)