Reputation: 1013
When declared like in the code below, $sessionTimeLeft
is undefined when being accessed inside updateSession()
. But when I moved $sessionTimeLeft
declaration and assignment inside initiate()
, I get the correct jQuery object. I think I can access $sessionTimeLeft
when it is declared inside initiate()
because of closure. But why is $sessionTimeLeft
out of scope on my original code?
var session = (function SessionManager() {
var timeLeftInMs;
var timeLeftInMin;
var delay; // in ms
var $sessionTimeLeft = $('#dcSessionTimeLeft');
/* Set up the module by setting the timeout and delay time. */
function initiate(_timeout, _delay) {
timeLeftInMin = _timeout;
timeLeftInMs = timeLeftInMin * 60 * 1000;
delay = _delay; // delay in ms
setInterval(updateSession, delay);
}
function updateSession() {
timeLeftInMs -= delay;
timeLeftInMin = timeLeftInMs / 60000; // convert ms to min.
$sessionTimeLeft.text(timeLeftInMin);
}
var publicAPI = {
initiate: initiate
};
return publicAPI;
})();
session.initiate(30,1000);
Upvotes: 1
Views: 56
Reputation: 21575
The problem here is that #dcSessionTimeLeft
is likely not yet loaded when you try to access it. So one way to ensure it is loaded is to wrap your code in a document.ready
:
$(function() {
var session = (function SessionManager() {
var timeLeftInMs;
var timeLeftInMin;
var delay; // in ms
var $sessionTimeLeft = $('#dcSessionTimeLeft');
/* Set up the module by setting the timeout and delay time. */
function initiate(_timeout, _delay) {
timeLeftInMin = _timeout;
timeLeftInMs = timeLeftInMin * 60 * 1000;
delay = _delay; // delay in ms
setInterval(updateSession, delay);
}
function updateSession() {
timeLeftInMs -= delay;
timeLeftInMin = timeLeftInMs / 60000; // convert ms to min.
$sessionTimeLeft.text(timeLeftInMin);
}
var publicAPI = {
initiate: initiate
};
return publicAPI;
})();
session.initiate(30,1000);
});
Upvotes: 1
Reputation: 158
The closure should work absolutely well in this case too. The reason this code is not working because you have not called the session function correctly. Remember this function is returning a object with a function initiate
Last line of the code should be
session.initiate(30,1000);
This should work. To reproduce the issue I used node. I changed the $sessionTimeLeft variable to a string hello and tested if its still accessible in updateSession function. My code is
var session = (function SessionManager() {
var timeLeftInMs;
var timeLeftInMin;
var delay; // in ms
var $sessionTimeLeft = "Hello";
/* Set up the module by setting the timeout and delay time. */
function initiate(_timeout, _delay) {
timeLeftInMin = _timeout;
timeLeftInMs = timeLeftInMin * 60 * 1000;
delay = _delay; // delay in ms
setInterval(updateSession, delay);
}
function updateSession() {
timeLeftInMs -= delay;
timeLeftInMin = timeLeftInMs / 60000; // convert ms to min.
console.log($sessionTimeLeft);
}
var publicAPI = {
initiate: initiate
};
return publicAPI;
})();
session.initiate(30,1000);
And the result I got is
Hello
Hello
Hello
Hello
Hello
each every 1 second.
Upvotes: 0