Im attempting to get a callback working inside a module in order to update a property. In this case I just want it to toggle the property value, and would like to be able to see that externally.
Here is the simple module
var Module = (function () {
// private
var isLoaded=false;
var timer = null;
var _privateMethod = function () {
console.log('hello from private')
}
//public
var publicMethod = function(){
console.log('in public method')
_privateMethod();
}
var start = function(){
console.log('starting timer')
timer = setInterval( function() {
console.log('timer callback')
isLoaded = !isLoaded;
},1000)
}
var stop = function(){
console.log('stopping timer')
clearInterval(timer)
}
return {
publicMethod: publicMethod,
isLoaded: isLoaded,
start: start,
stop: stop,
}
})();
module.exports = Module;
and im testing it with this
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
var DM = require('./module.js')
DM.publicMethod()
DM.start()
console.log(DM.isLoaded)
sleep(500)
console.log(DM.isLoaded)
sleep(500)
console.log(DM.isLoaded)
sleep(500)
console.log(DM.isLoaded)
sleep(500)
DM.stop();
It doesnt toss an error, and it looks like its starting the timer ok but im never getting the output from the callback and the property isnt updating. Im guessing its a scope issues, but I cant put my finger on it.
To do this (with that general structure), you have two options:
Keep a reference to the object you return:
var obj;
// ...
obj = {
publicMethod: publicMethod,
isLoaded: false,
start: start,
stop: stop,
};
return obj;
...and remove the isLoaded
variable, and instead set obj.isLoaded = true
in the callback.
Live example:
var Module = (function() {
var obj;
var timer = null;
var start = function(){
console.log('starting timer')
timer = setInterval( function() {
console.log('timer callback')
obj.isLoaded = !obj.isLoaded;
},1000)
};
var stop = function(){
console.log('stopping timer')
clearInterval(timer)
};
obj = {
//publicMethod: publicMethod,
isLoaded: false,
start: start,
stop: stop,
};
return obj;
})();
Module.start();
var t = setInterval(function() {
console.log("Module.isLoaded = " + Module.isLoaded);
}, 500);
setTimeout(function() {
console.log("Stopping");
clearInterval(t);
Module.stop();
}, 10000);
.as-console-wrapper {
max-height: 100% !important;
}
This has the advantage of being read-only:
return {
publicMethod: publicMethod,
get isLoaded() {
return isLoaded;
},
start: start,
stop: stop,
};
Live example:
var Module = (function() {
var isLoaded = false;
var timer = null;
var start = function(){
console.log('starting timer')
timer = setInterval( function() {
console.log('timer callback')
isLoaded = !isLoaded;
},1000)
};
var stop = function(){
console.log('stopping timer')
clearInterval(timer)
};
obj = {
//publicMethod: publicMethod,
get isLoaded() {
return isLoaded;
},
start: start,
stop: stop,
};
return obj;
})();
Module.start();
var t = setInterval(function() {
console.log("Module.isLoaded = " + Module.isLoaded);
}, 500);
setTimeout(function() {
console.log("Stopping");
clearInterval(t);
Module.stop();
}, 10000);
.as-console-wrapper {
max-height: 100% !important;
}