I am trying to develop in Nodejs using its evented system. I've implemented the following code and it passes my tests (using mocha). However, I am not confident that it will work in a production environment because of the the scope of the that
variable.
In my code, I assign that=this
. Afterwards I assign the config
object to that.config
and the callback emits the event without passing config as a parameter. Then the listener function uses the that.config
to emit another signal. The cache object is a request to a redis database.
The question is: will the that.config
object always refer to the scope when I've emitted the signal or could it be modified by another request (that gets another config) after the first emitted signal but before the first listener uses that.config
(inside another callback)?
function SensorTrigger(sensorClass, configClass) {
this.sensorClass = sensorClass || {'entityName': 'sensor'};
this.configClass = configClass || {'entityName': 'config'};
this.cache = new CacheRedis(app.redisClient, app.logmessage);
events.EventEmitter.call(this);
}
util.inherits(SensorTrigger, events.EventEmitter);
SensorTrigger.prototype.getSensorConfig = function(sensor, trigger) {
var that = this
, sensorKeyId = that.sensorClass.entityName + ':' + sensor
, baseKeyId = "base";
that.trigger = trigger;
that.id = sensor;
var callBack = function (config) {
config = utils.deepen(config);
that.receiver = config.receiver;
that.config = config.triggers[that.trigger];
that.emit(that.config.data, sensor);
}
that.cache.getItem(that.configClass, sensorKeyId, function(err, config) {
if (!config) {
that.cache.getItem(that.configClass, baseKeyId, function(err, config) {
callBack(config);
})
} else {
callBack(config);
}
})
}
SensorTrigger.prototype.getAllData = function(sensor) {
var that = this;
that.cache.getAllData(that.sensorClass, sensor, function(err, data) {
if (err) {
that.emit("error", err);
} else {
that.emit(that.config.aggregation, sensor, data);
}
})
}
trigger = new SensorTrigger();
trigger.on("onNewData", trigger.getSensorConfig);
trigger.on("all", trigger.getAllData);
An example of the config object:
{
"id": "base",
"triggers.onNewData.data": "all",
"triggers.onNewData.aggregation": "max",
"triggers.onNewData.trigger": "threshold",
"receiver.host": "localhost",
"receiver.port": "8889",
"receiver.path": "/receiver"
}
Only if the next time it runs "that" is changed to a different instance of this
. Since each instance has it's own function, the only way that could happen is if you do something like:
var trigger = new SensorTrigger(sensor, config);
trigger.getSensorConfig.apply(SOMETHING_ELSE, sensor2, trigger2);
As long as you use it like you normally would:
var trigger = new SensorTrigger(sensor, config);
trigger.getSensorConfig(sensor2, trigger2);
//or even:
trigger.getSensorConfig.apply(trigger, sensor2, trigger2);
It is fine. What you are doing is a common practice in JavaScript, and used in production all the time.