如何重置和设置计时器功能?

时间:2016-09-27 14:34:16

标签: javascript angularjs

我有一个带控制器的测验应用程序,我应该设置一个应该计数30秒的计时器,然后在那段时间没有活动时停止测验。如果在此期间有某些活动,则应重置并再次开始计数。我为此设置了Web套接字侦听器。我该如何设置定时器?

这是我的控制者:

angular.module('quiz.controllers')
.controller('MultiPlayerQuestionController', function(
  $scope,
  $rootScope,
  $state,
  $stateParams,
  $timeout,
  UserService,
  QuizService,
  InviteService,
  MessageService,
  SocketService
) {
  $scope.user = UserService.get();
  $scope.quiz = QuizService.getCurrent();
  $scope.opponent = $scope.user.player.id == $scope.quiz.players[0].id
    ? $scope.quiz.players[1]
    : $scope.quiz.players[0]
    || null;

  $scope.currentQuestion = {};
  $scope.answer = {};
  $scope.showAlternatives = false;
  $scope.showCorrect = false;
  $scope.isLast = false;
  $scope.opponentAnswered = false;

  var timeouts = {
    stop: null,
    activate: null
  };

  var startTime,
      loadBar,
      initiated = false;

  // Opponent has answered; update score display
  SocketService.socket.removeAllListeners('gameEvent:opponentAnswer');
  SocketService.socket.on('gameEvent:opponentAnswer', function(message) {
    $scope.opponentAnswered = true;
    QuizService.updateOpponentScore(message.data.totalScore);
  });

  // Next question is triggered from all players having answered
  SocketService.socket.removeAllListeners('gameEvent:nextQuestion');
  SocketService.socket.on('gameEvent:nextQuestion', function(message) {
    $timeout(function() {
      QuizService.setCurrentQuestion(message.data.question);
      setupQuestion(message.data.question);
    }, 3000);
  });

  // Game is finished, go to score screen
  SocketService.socket.removeAllListeners('gameEvent:quizFinished');
  SocketService.socket.on('gameEvent:quizFinished', function(message) {
    stopQuiz();

    $timeout(function() {
      $state.go('multiplayer.score');
    }, 3000);
  });

  // An opponent has quit, go to score screen
  SocketService.socket.removeAllListeners('gameEvent:opponentQuit');
  SocketService.socket.on('gameEvent:opponentQuit', function(message) {
    stopQuiz();
    MessageService.alertMessage('Motstanderen din har enten gitt opp eller blitt frakoblet.');
    $state.go('multiplayer.score');
  });

  // Disconnected. Go back to home screen.
  SocketService.socket.removeAllListeners('reconnecting');
  SocketService.socket.on('reconnecting', function() {
    MessageService.alertMessage('Du har mistet tilkoblingen. Spillet har blitt avbrutt.');
    SocketService.socket.removeAllListeners('reconnecting');
    $state.go('main.front');
  });

  // The app was paused (closed), equals giving up.
  var pauseEvent = $rootScope.$on('app:paused', function() {
    QuizService.giveUpCurrent($scope.user.player);

    var resumeEvent = $rootScope.$on('app:resumed', function() {
      stopQuiz();
      $state.go('multiplayer.score');
      resumeEvent();
    });

    pauseEvent();
  });

  /**
   * Give up the current quiz.
   */
  $scope.giveUp = function (player) {
    MessageService.confirm('Ønsker du å avbryte quizen?').then(function(result) {
      if (result) {
        QuizService.giveUpCurrent(player);
        $state.go('multiplayer.score', {}, { reload: true });
        stopQuiz();
      }
    });
  };

  /**
   * Go to next question for current quiz.
   */
  $scope.nextQuestion = function() {
    $timeout.cancel(timeouts.stop);
    $timeout.cancel(timeouts.activate);

    QuizService.nextQuestion().$promise.then(function(question) {
      setupQuestion(QuizService.getCurrentQuestion());
    });
  };

  /**
   * Finish quiz.
   */
  $scope.finish = function() {
    QuizService.finish();
    $state.go('multiplayer.score');
  };

  /**
   * Choose an alternative (aka answer current question).
   */
  $scope.chooseAlternative = function(alternative) {
    if (!$scope.showAlternatives || $scope.showCorrect) {
      return;
    }

    var answerTime = Date.now() - startTime;

    $scope.answer = alternative;
    QuizService.answer(alternative, answerTime);

    if (timeouts.stop) {
      $timeout.cancel(timeouts.stop);
    }

    stopQuestion();
  };

  /**
   * Set up a new question - change data and start countdown to activate question.
   */
  var setupQuestion = function(question) {
    $scope.showAlternatives = false;
    $scope.showCorrect = false;
    $scope.currentQuestion = question;
    $scope.answer = {};
    $scope.isLast = parseInt($scope.quiz.questionCount) == parseInt($scope.currentQuestion.questionNumber);

    var prepareTime = 5000;

    var newLoadBar = loadBar.cloneNode(true);
    loadBar.parentNode.replaceChild(newLoadBar, loadBar);
    loadBar = newLoadBar;

    setAnimationDuration(loadBar, 'loadbar', prepareTime);
    timeouts.activate = $timeout(activateQuestion, prepareTime);
  };

  /**
   * A question timed out; stop and send empty answer.
   */
  var questionTimeout = function() {
    // Delay answering by a random delay between 0 and 500ms.
    $timeout(function() {
      stopQuestion();
      QuizService.noAnswer($scope.currentQuestion.id);
    }, Math.floor((Math.random() * 500) + 1));
  };

  /**
   * Activate the current question: show alternatives and open answering.
   */
  var activateQuestion = function() {
    $scope.showAlternatives = true;
    var timeToAnswer = 10000;
    startTime = Date.now();

    var newLoadBar = loadBar.cloneNode(true);
    loadBar.parentNode.replaceChild(newLoadBar, loadBar);
    loadBar = newLoadBar;

    setAnimationDuration(newLoadBar, 'loadbar', timeToAnswer);
    timeouts.stop = $timeout(questionTimeout, timeToAnswer);
  };

  /**
   * Stop the current question and show the correct answer info.
   */
  var stopQuestion = function() {
    $scope.showCorrect = true;
    stopAnimation(loadBar);
    $timeout.cancel(timeouts.stop);
  };

  /**
   * End the current quiz.
   */
  var stopQuiz = function() {
    SocketService.socket.removeAllListeners('gameEvent:opponentAnswer');
    SocketService.socket.removeAllListeners('gameEvent:nextQuestion');
    SocketService.socket.removeAllListeners('gameEvent:quizFinished');
    SocketService.socket.removeAllListeners('gameEvent:opponentQuit');
    SocketService.socket.removeAllListeners('reconnecting');

    $timeout.cancel(timeouts.stop);
    $timeout.cancel(timeouts.activate);
  };

  /**
   * Set the animation duration for an element. Used to stop and start the
   * progress bar.
   */
  var setAnimationDuration = function(element, keyframes, duration) {
    var animationSetting = keyframes + ' ' + duration + 'ms linear';

    element.style.webkitAnimation = animationSetting;
    element.style.animation = animationSetting;
  }

  var stopAnimation = function(element) {
    element.style.webkitAnimation = 'none';
    element.style.animation = 'none';
  };

  if (!initiated) {
    initiated = true;
    loadBar = document.getElementById('load-bar');
    setupQuestion(QuizService.getCurrentQuestion());
  }


});

我试过调用我在控制器中创建的responseTimer函数。在文件的乞讨中,我这样称呼它:

responseTimer(30000);

然后我会这样定义:

var responseTimer = function (time) {
    responseTimer = $timeout(stopQuiz, time);
    console.log('Started timer');
  };

  var resetResponseTimer = function () {
      $timeout.cancel(responseTimer);
      responseTimer(30000);
      console.log("Timer reset");
  };

但是我收到了一个错误:

  

TypeError:responseTimer不是函数

2 个答案:

答案 0 :(得分:1)

问题来自范围冲突。在你的代码中

// responseTimer is declared as a global function
var responseTimer = function (time) {

   // as the var keyword is not specify, scope of responseTimer becomes global and not local and overrides the previous declaration
   responseTimer = $timeout(stopQuiz, time);

这就是你得到错误的原因

 responseTimer is not a function

要解决此问题,请在第二个声明之前添加var关键字,并相应地命名变量。一个好的做法是在命名函数/对象的方法时添加一个动作动词,在你的情况下,triggerResponseTimer作为你的函数的名称,responseTimer作为变量的名称,所以最终的定位是:

var triggerResponseTimer = function (time) {

    var responseTimer = $timeout(stopQuiz, time);

答案 1 :(得分:0)

你最好使用$ intervall: 在这里你会找到一个很好的样本: http://tutorials.jenkov.com/angularjs/timeout-interval.html

同样好样品: https://docs.angularjs.org/api/ng/service/ $间隔