title: Trying to access a global variables method in javascript, but only works certain times
body: <p>I have three files: tasker_matic.js, tasker.js, and tasker.html. I am not allowed to edit tasker.html or tasker.js AT ALL. I am to use tasker_matic to communicate with the tasker.js library. </p>
  
  <p>Right now I am trying to access its login function. When the login is correct, it should pop up with an alert saying it worked, and when it isn't correct, it should pop up with an alert saying forbidden. This is where I am having the problem. If I continually click on the login button, it will eventually pop up with an alert, but not every time. Does anyone know why this is? </p>
  
  <p>Tasker_matic.js:</p>
  
  <pre><code>function login(e) {
      var userName = document.getElementById("usernameInput").value;
      var password = document.getElementById("passwordInput").value;
      tasker.login( userName, password, (err, user) =&gt; {
          if (err) {
              alert( err );
          }
          else if (user) {
              alert("it worked");
          }
      });
  }
  
   function createTask(s) {
       let descNode;
       let theTable = document.getElementById('tasks');
       let row = document.createElement('tr');
       let description = document.createElement('th');
       descNode = document.createTextNode(s);
       description.append(descNode);
       row.append(description);
       theTable.append(row);
  
   }
  </code></pre>
  
  <p>tasker.html:</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en" xmlns="http://www.w3.org/1999/xhtml"&gt;
  &lt;head&gt;
      &lt;meta charset="utf-8" /&gt;
      &lt;title&gt;Tasker&lt;/title&gt;
      &lt;script src="tasker.js"&gt;&lt;/script&gt;
      &lt;link rel="stylesheet" href="tasker_matic.css"&gt;
      &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"&gt;
      &lt;script src="tasker_matic.js"&gt;&lt;/script&gt;    
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div class="container"&gt;
  
      &lt;div id="login" class="on"&gt;
        &lt;h1&gt;Login&lt;/h1&gt;&lt;br&gt;
          &lt;form style="width:50%"&gt;
            &lt;input id="usernameInput" type="text" name="username" placeholder="Username" class="form-control"&gt;
            &lt;input id="passwordInput" type="password" name="password" placeholder="Password" class="form-control"&gt;
            &lt;input type="submit" value="Login" class="btn btn-primary pull-right" onclick="login(event)"&gt;
          &lt;/form&gt;
      &lt;/div&gt;
  
      &lt;div id="home" class="off"&gt;
        &lt;h1&gt;Tasker &lt;small&gt;&lt;span class="pull-right btn btn-primary btn-sm" id="logout" onclick="logout()"&gt;&lt;/span&gt;&lt;/small&gt;&lt;/h1&gt;
        &lt;div class="well well-sm"&gt;
          &lt;form class="form-inline"&gt;
            &lt;div class="form-group"&gt;
              &lt;label for="descField"&gt;Description&lt;/label&gt;
              &lt;input class="form-control" type="text" placeholder="Description" id="descField"&gt;
            &lt;/div&gt;
  
            &lt;div class="form-group"&gt;
              &lt;label for="cField"&gt;Color Code&lt;/label&gt;
              &lt;input class="form-control" type="color" id="cField"/&gt;
            &lt;/div&gt;
  
            &lt;div class="form-group"&gt;
              &lt;label for="dField"&gt;Due Date&lt;/label&gt;
              &lt;input class="form-control" type="date" id="dField"/&gt;
            &lt;/div&gt;
  
            &lt;input class="form-control" type="button" value="+" id="addButton" onclick="addTask()"/&gt;
          &lt;/form&gt;
        &lt;/div&gt;
  
        &lt;div class="well well-sm"&gt;
          &lt;form class="form-inline"&gt;
            &lt;input class="form-control" type="text" placeholder="search" id="searchField" style="width:25%" onkeyup="searchTextChange()"/&gt;
            &lt;div class="checkbox"&gt;
              &lt;label&gt;
                &lt;input type="checkbox" id="incompleteBox" onclick="incompleteChange()"/&gt;Incomplete Only
              &lt;/label&gt;
  
            &lt;/div&gt;
            &lt;div class="checkbox"&gt;
              &lt;label&gt;
                &lt;input type="checkbox" id="overdueBox" onclick="overdueChange()"/&gt;Over-due only
              &lt;/label&gt;
            &lt;/div&gt;
          &lt;/form&gt;
        &lt;/div&gt;
  
        &lt;table id="tasks" class="table table-striped"&gt;
        &lt;/table&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>tasker.js:</p>
  
  <pre><code>let tasker = (function () {
      let verbs = [
          "make",
          "install",
          "update",
          "generate data for",
          "talk to",
          "schedule a time for",
          "develop a plan for",
          "knit",
          "create",
          "build",
          "write",
          "get",
          "finish",
          "call",
          "arrange",
          "submit",
          "talk to",
          "do",
          "protest",
          "collect",
          "shop for"
      ];
  
      let nouns = [
          "a cake",
          "the boat",
          "our wedding",
          "the garage",
          "the tow truck",
          "our shed",
          "1090 tax form",
          "the IRS agent",
          "milk",
          "some LED lights",
          "monthly budget",
          "marketing plan",
          "the flowers",
          "an albatross"
      ];
  
      let userNames = [
          "frodo baggins",
          "gandalf gray",
          "smaug dragon"
      ];
  
      let Task = function (id, ownerId, desc, due, color, complete) {
          this.ownerId = ownerId;
          this.desc = desc;
          this.due = due;
          this.color = color;
          this.complete = complete;
          this.id = id || randomId();
      };
  
      let randomId = function () {
          return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
              var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r &amp; 0x3 | 0x8);
              return v.toString(16);
          });
      }
  
      let randomColor = function () {
          let pad = function (v) {
              return v.length == 1 ? '0' + v : v;
          }
          r = Math.floor(Math.random() * 256).toString(16);
          g = Math.floor(Math.random() * 256).toString(16);
          b = Math.floor(Math.random() * 256).toString(16);
          return '#' + pad(r) + pad(g) + pad(b);
      }
  
      let randomDate = function () {
          year = Math.floor(Math.random() * 14 + 2010);
          month = Math.floor(Math.random() * 12);
          day = Math.floor(Math.random() * 31);
          return new Date(year, month, day);
      };
  
      let choose = function (things) {
          let i = Math.floor(Math.random() * things.length);
          return things[i];
      }
  
      let randomDescription = function () {
          return choose(verbs) + ' ' + choose(nouns);
      };
  
      let makeList = function (ownerId, n) {
          result = [];
          for (i = 0; i &lt; n; i += 1) {
              result.push(new Task(null,
                  ownerId,
                  randomDescription(),
                  randomDate(),
                  randomColor(),
                  choose([true, false])));
          }
          return result;
      }
  
      let updateTask = function( oldTask, editedTask ) {
          let propertiesToCopy = ['desc', 'due', 'color', 'complete' ];
          propertiesToCopy.forEach( prop =&gt; {
              if( editedTask.hasOwnProperty( prop ) ) {
                  oldTask[prop] = editedTask[prop];
              }
          });
      }
  
      let state = {
          users: userNames.reduce(function (acc, cv) {
              let parts = cv.split(' '); //
              let name = parts[0];
              let email = parts[0][0] + parts[1] + '@uwlaxer.edu';
              let id = randomId();
              let password = parts[1];
              let tasks = makeList(id, Math.random() * 50 + 20).reduce((acc, t) =&gt; { acc[t.id] = t; return acc; }, {});
              acc[id] = {
                  name: name,
                  email: email,
                  id: id,
                  password: password,
                  tasks: tasks
              };
              return acc;
          }, {}),
          user: null
      };
  
      let getTask = function (ownerId, id) {
          try {
              return state.users[ownerId].tasks[id];
          } catch (e) {
              return null;
          }
      }
  
      let getUserByName = function (name) {
          for (id in state.users) {
              if (state.users[id] &amp;&amp; state.users[id].name === name) {
                  return state.users[id];
              }
          }
          return null;
      }
  
      let taskList = function (ownerId) {
          let result = [];
          for (let tid in state.user.tasks) {
              result.push(state.user.tasks[tid]);
          }
          return result.sort((a, b) =&gt; b.due.getTime() - a.due.getTime());
      }
  
      let respond = function (error, value, cb) {
          window.setTimeout(() =&gt; cb(error, value), Math.random() * 1500);
      }
  
      let copyTask = function( task ) {
          return new Task(task.id, task.ownerId, task.desc, task.due, task.color, task.complete);
      }
  
      return {
          login: function ( username, passwd, cb) {
              let user = getUserByName( username );
              if (user &amp;&amp; user.password === passwd) {
                  state.user = user;
                  let cleansedUser = { name: user.name, email: user.email, id: user.id };
                  respond(null, cleansedUser, cb);
              } else {
                  respond('forbidden', null, cb);
              }
          },
  
          logout: function (cb) {
              state.user = null;
              respond(null, true, cb);
          },
  
          tasks: function (ownerId, cb) {
              if (ownerId === state.user.id) {
                  let tasks = taskList(ownerId).map(u =&gt; new Task(u.id, u.ownerId, u.desc, u.due, u.color, u.complete));
                  respond(null, tasks, cb);
              } else {
                  respond('forbidden', null, cb);
              }
          },
  
          add: function (ownerId, task, cb) {
              if (state.user.id == ownerId) {
                  if (task.desc &amp;&amp; task.due &amp;&amp; task.color) {
                      let due = new Date(task.due);
                      let task = new Task(task.id, ownerId, task.desc, due, task.color, Boolean(task.complete));
                      state.users[ownerId].tasks[task.id] = task;
                      respond(null, task, cb);
                  } else {
                      respond('invalid task', null, cb);
                  }
              } else {
                  respond('forbidden', null, cb);
              }
          },
  
          delete: function (ownerId, taskId, cb) {
              if (state.user.id === ownerId) {
                  let task = state.users[ownerId].tasks[taskId];
                  delete state.users[ownerId].tasks[taskId];
  
                  if (task) {
                      respond(null, task, cb);
                  } else {
                      respond('no such task', null, cb);
                  }
              } else {
                  respond('forbidden', null, cb);
              }
          },
  
          edit: function (ownerId, taskId, task, cb) {
              if (state.user.id == ownerId) {
                  if (taskId) {
                      let oldTask = getTask(ownerId, taskId);
                      if( oldTask) {
                          updateTask( oldTask, task );                        
                          respond( null, copyTask( oldTask ), cb );
                      } else {
                          respond( 'no such task', null, cb );
                      }                    
                  } else {
                      respond( 'no such task', null, cb );
                  }
              } else {
                  respond( 'forbidden', null, cb );
              }
          }
      }
  
  })();
  </code></pre>