1

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);
7
  • session.initiate(30, 1000) Commented Jul 28, 2016 at 21:29
  • 1
    Is #dcSessionTimeLeft loaded when you assign it to $sessionTimeLeft ? Commented Jul 28, 2016 at 21:29
  • 1
    Please provide code to reproduce the issue. Commented Jul 28, 2016 at 21:30
  • Its an excellent question if it's true. I don't know why people are down marking it Commented Jul 28, 2016 at 21:44
  • @TejaswiSharma it could be quite interesting. But it also could be down to the fact that the element with id dcSessionTimeLeft doesn't exist when the module is created Commented Jul 28, 2016 at 21:45

2 Answers 2

1

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);
});
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.