programing

AngularJS로 1초마다 카운트다운하는 메시지를 표시하려면 어떻게 해야 합니까?

goodsources 2023. 9. 28. 08:21
반응형

AngularJS로 1초마다 카운트다운하는 메시지를 표시하려면 어떻게 해야 합니까?

서버와의 연결을 확인하기 위해 사용하는 코드가 있습니다.내 코드는 60초마다 실행됩니다.코드가 실행되면 메시지가 생성되고 페이지에 표시됩니다.지금까지 제가 한 것은 다음과 같습니다.

확인하는 코드:

$interval(function () {
        us.isConnected().then(closeConnect, openConnect);
    }, 60 * 1000);

검사를 수행하는 코드는

isConnected = (): ng.IPromise<any> => {
    var self = this;
    var deferred = this.$q.defer();
    this.$http({
        method: 'GET',
        url: self.ac.baseUrl + '/api/Connect/Verify'
    })
        .success(() => {
            self.connects = 0;
            self.connectMessage = null;
            deferred.resolve();
        })
        .error(() => {  
            if (self.connects == 0) {
                self.connectMessage = "Unable to establish a connection to the server. " + retryMessage();
            } else if (self.connects == 1) {
                self.connectMessage = "Unable to establish a connection to the server for " + self.connects + " minute" + retryMessage();
            } else {
                self.connectMessage = "Unable to establish a connection to the server for " + self.connects + " minutes." + retryMessage();
            }
            self.connects++; 
            deferred.reject();
        });
    return deferred.promise;
};

다음과 같은 메시지를 줄 수 있는 retryMessage()라는 간단한 기능을 사용하고 싶습니다.

 Unable to establish a connection to the server for 164 minutes. 
 Connection will be retried in 59 seconds.
 Unable to establish a connection to the server for 164 minutes. 
 Connection will be retried in 58 seconds.
 Unable to establish a connection to the server for 164 minutes. 
 Connection will be retried in 57 seconds.
 ...
 Unable to establish a connection to the server for 164 minutes. 
 Connection will be retried in 1 seconds.
 Unable to establish a connection to the server for 164 minutes. 
 Retrying connection now.
 Unable to establish a connection to the server for 165 minutes. 
 Connection will be retried in 59 seconds.

재점검이 있을 때 0까지 초 단위로 카운트다운을 합니다.

Angular에서 방법을 제안해 줄 수 있는 사람?이 카운트다운을 달성할 수 있는 JS?

당신이 시도하고 있는 일을 하는 한 가지 가능한 방법은$q.notify와 공동으로$interval.

확인 및 거부와 함께 다른 메시지를 전달할 수 있습니다.물론 이 작업을 수행하는 모든 장소에서 대신 로깅 서비스로 바로 인쇄할 수도 있지만, 이러한 메시지를 약속 동작과 함께 반환하는 것이 적절할 수도 있다고 생각했습니다(원하는 경우 상태 코드 및 기타 데이터가 포함된 개체를 메시지와 함께 반환할 수도 있음).

아래 샘플에서는 컨트롤러가 로깅을 관리하도록 하고 출력을 12라인으로 제한했습니다.또한 연결 테스트를 위한 매개 변수를 지정하여 60초마다, 20회마다 연결을 시도합니다(이 매개 변수들은 다른 간격, 다른 횟수로 또는 무기한으로 시도하도록 변경될 수 있음).테스트가 실패한 경우 재시도 시도 전까지 매초마다 재시도 메시지를 출력합니다.

(function() {
  "use strict";

  var myApp = angular.module('myApp', []);
  myApp.controller('MainController', ['$scope', 'us', '$log', MainController]);
  myApp.service('us', ['$interval', '$q', '$http', '$log', usService]);

  /* Controller */
  function MainController($scope, us, $log) {

    var _data = {
        connectLog: null
      },
      _connectMessages = [],
      _MAX_LOG_LINES = 12;

    $scope.data = _data;

    _log("Starting connection test...");
    us.testConnection(60, 20) //60 seconds between tests, 20 tests (if no max specified, could run forever...)
      .then(onTestsSuccessful, onTestsFailed, onNotifying);

    function onTestsSuccessful(result) {
      _log(result);
      // do success stuff...
    }

    function onTestsFailed(result) {
      _log(result);
      // do failed stuff...
    }

    function onNotifying(result) {
      _log(result);
      //do retrying stuff...
    }

    function _log(message, deferOutput) {
      //$log.debug(message);

      _connectMessages.push(message);

      if (_MAX_LOG_LINES && _connectMessages.length > _MAX_LOG_LINES) {
        _connectMessages.splice(0, _connectMessages.length - _MAX_LOG_LINES);
      }

      if (!deferOutput) {
        _data.connectLog = _connectMessages.join('\n');
      }
    }
  }

  /* Service */
  function usService($interval, $q, $http, $log) {

    var _testConnectionInterval,
      _testsRun;

    return {
      testConnection: _startTestConnection
    };

    function _startTestConnection(secondsBetweenTests, maxTests) {
      var deferred = $q.defer(),
        connectAttempts = 0;

      _cancelConnectionTest();

      _connectionTest().then(onConnectionTestSuccess, onConnectionTestFail); //immediately do first test
      _testsRun++;

      if (secondsBetweenTests > 0) {
        _testConnectionInterval = $interval(
          function repeatConnectionTest() {
            if (maxTests && _testsRun >= maxTests) {
              return _cancelConnectionTest();
            }
            deferred.notify("Retrying connection now.");
            _connectionTest().then(onConnectionTestSuccess, onConnectionTestFail);
            _testsRun++;
          },
          secondsBetweenTests * 1000); //start the countdown to the next
      }

      function onConnectionTestSuccess(result) {
        connectAttempts = 0;

        if ((maxTests && _testsRun >= maxTests) || !secondsBetweenTests) {
          deferred.resolve("Last connection test success, " + _testsRun + " tests complete.");
        } else {
          deferred.notify("Connection test success.");
        }
      }

      function onConnectionTestFail(result) {
        var minutesPassed = connectAttempts * secondsBetweenTests / 60,
            minutesRoundedToTwoDec = +(Math.round(minutesPassed + "e+2")  + "e-2");
        
        var connectMessage = "Unable to establish a connection to the server" + (connectAttempts === 0 ? "." : " for " + minutesRoundedToTwoDec + " minute" + (minutesPassed > 1 ? "s." : "."));

        connectAttempts++;

        if ((maxTests && _testsRun >= maxTests) || !secondsBetweenTests) {
          deferred.reject("Last connection test failed, " + _testsRun + " tests completed.");
        } else {
          deferred.notify(connectMessage);
          deferred.notify("Connection will be retried in " + secondsBetweenTests + " seconds.");

          var retryInterval = $interval(
            function retryMessage(counter) {
              deferred.notify(connectMessage);

              var secondsLeft = (secondsBetweenTests - 1) - counter;
              deferred.notify("Connection will be retried in " + secondsLeft + " second" + (secondsLeft > 1 ? "s." : "."));

              if (!secondsLeft) {
                $interval.cancel(retryInterval);
                retryInterval = null;
              }
            },
            1000, (secondsBetweenTests - 1));
        }
      }

      return deferred.promise;
    }

    function _connectionTest() {
      var deferred = $q.defer(),
        getBroken = {
          method: 'GET',
          url: '/api/never/gonna/give/you/up'
        };

      $http(getBroken)
        .success(function onSuccess() {
          deferred.resolve('Success!');
        })
        .error(function onError() {
          deferred.reject('Failure!');
        });

      return deferred.promise;
    }

    function _cancelConnectionTest() {
      _testsRun = 0;
      if (!_testConnectionInterval) {
        $log.debug("No previously running connection test to cancel.");
        return;
      }
      $log.debug("Cancelling connection test.");
      $interval.cancel(_testConnectionInterval);
      _testConnectionInterval = null;
    }
  }

})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<div ng-app="myApp">
  <pre ng-controller="MainController">{{data.connectLog}}</pre>
</div>

이렇게 60초부터 카운트다운을 할 수 있습니다.

countdown(60);

  function countdown(current_time){
    if(current_time === 0){
      //call function to connect to server
      return;
    }
    else{
      current_time--;
    }
    $scope.time = current_time;
    $timeout(function(){countdown(current_time)}, 1000);
  }

코데펜

오류 메시지를 html에 넣고 a로 숨기는 것을 추천합니다.ng-show아니면ng-if그런 다음 번호를 변경하면 모든 텍스트를 반복해서 추가할 필요가 없습니다.

지시사항을 사용할 필요는 없다고 생각합니다, 아마 컨트롤러 안에서 모든 것을 할 수 있을 겁니다.구현 방법이 무엇입니까?closeConnection그리고.openConnection'시작'과 '중지'를 추가하는 메서드를 편집해야 합니다.$interval.

그리고 기억하세요.$interval이 경우 매우 유용한 최대 재귀 횟수를 사용합니다.

https://docs.angularjs.org/api/ng/service/$interval

function controllerFunc($scope, $interval) {
    var timer;
    var lastConnection = 0;
    $scope.message = '';

    //this is what you already have
    $interval(function () {
        us.isConnected().then(closeConnect, openConnect);
    }, 60 * 1000);
    //...

    function closeConnect() {
        //...
        $interval.cancel(timer);
        lastConnection = 0;
    }

    function openConnect() {
        //...
        timer = $interval(timerCall, 1000, 60);
        lastConnection++;
    }

    function timerCall(times) {
        $scope.message += 'Unable to establish a connection to the server for ' + lastConnection + ' minutes. ';

        var retry = 60 - times;
        $scope.message += 'Connection will be retried in '+ retry +' seconds';
    }
}

메시지 서식 지정

$scope.message는 이 수 다 수 .ng-bind-html를 입력한 html합니다를음합니다.

https://docs.angularjs.org/api/ng/directive/ngBindHtml

<div ng-bind-html="message"></div>

그래서 js를 바꿉니다.

$scope.message += '<p>Connection will be retried in '+ retry +' seconds</p>';

저도 아주 비슷한 목적의 지시가 있습니다. 여기 플렁커에서 확인하실 수 있습니다.

기본적으로 (1) timer & (2) refresh-state를 사용하며, 또한 지시 속성에서 읽혀지는 타임아웃에 대해 몇 초 안에 구성할 수 있습니다.

주어진 구간 이후에 주어진 함수를 호출하고, 또한 $scope 변경에 대한 #구간을 파괴합니다.

아래는 그것에 대한 코드입니다.

app.directive("csAutoRefresh", ["$interval", function ($interval) {

    var templateFn = function () {
        var template = '<div class="text-left alert alert-success nopadding"';
        template += 'style="margin-bottom: 0; margin-right: 0"> ';
        template += ' <button class="btn btn-link" data-ng-click="factory.refresh.toggle()">';
        template += '{{factory.refresh.refreshText()}}</button>';
        template += '<span>...Refreshing upload status in ';
        template += ' {{state.timer.timePending}} seconds</span>';
        template += ' </div>';
        return template;
    };

    var linkFn = function (scope) {
        scope.pauseOn = scope.pauseOn === true;
        scope.isprocessing = false;

        scope.state = {
            refresh : {
                suspend : false
            },
            timer : {
                timePending: 0,
                refreshInterval : 60
            }
        }

        function doRefresh() {
            var refresh = {
                pause: function () { scope.state.refresh.suspend = true; },
                cont: function () { scope.state.refresh.suspend = false; },
                toggle: function () { scope.state.refresh.suspend = !scope.state.refresh.suspend; },
                refreshText: function () { return scope.state.refresh.suspend ? "Resume Refresh" : "Pause Refresh"; }
            };
            return refresh;
        }

        function doTimer() {
            var timer = {
                reset: function () { scope.state.timer.timePending = scope.state.timer.refreshInterval; },
                update: function () {
                    if (scope.state.timer.timePending < 0) timer.reset();
                    scope.state.timer.timePending--;
                },
                done: function () { return scope.state.timer.timePending <= 0; },
                force: function () { scope.state.timer.timePending = 0; }
            };
            return timer;
        };

        scope.factory = {
            refresh: doRefresh(),
            timer: doTimer()
        };

        if (angular.isDefined(scope.interval) && parseInt(scope.interval) > 0) {
            scope.state.timer.refreshInterval = scope.interval;
        }
        scope.factory.timer.reset();

        scope.$watch(function () {
            return scope.state.timer.timePending;
        }, function () {
            if (!scope.factory.timer.done()) return;
            var result = scope.$eval(scope.onTimeout);
            if (angular.isObject(result) && angular.isFunction(result.then)) {
                scope.isprocessing = false;
                scope.factory.timer.reset();
                result.finally(function () { scope.factory.timer.reset(); });
            } else {
                scope.isprocessing = false;
                scope.factory.timer.reset();
            }
        });

        scope.$watch('pauseOn', function () {
            if (scope.pauseOn) {
                scope.factory.refresh.pause();
            } else {
                scope.factory.timer.reset();
                scope.factory.refresh.cont();
            }
        });

        var updateTimer = function () {
            if (scope.isprocessing) return;
            if (scope.state.refresh.suspend) return;
            scope.factory.timer.update();
        };

        var interval = $interval(updateTimer, 1000);
        scope.$on('$destroy', function () {
            $interval.cancel(interval);
        }); 
    };

    return {
        restrict: 'E',
        scope: { onTimeout: '&', pauseOn: '=', interval: '@' },
        template: templateFn,
        link: linkFn,
    };
}]);
$interval(function () {
    us.isConnected().then(closeConnect, openConnect);
}, 1000);

것은 아니다.

$interval(function () {
    us.isConnected().then(closeConnect, openConnect);
}, 20 * 1000);

후자는 20초(20*1000ms)마다 검사를 수행하므로 실제 검사 코드가 버그가 없는 한 1초마다 실행해야 합니다.

따라서 세부 정보를 사용자에게 어떻게 출력할지에 따라 이 지침을 만들고 그 안의 모든 것을 제어하는 것이 가장 좋을 것입니다.

원하는 작업을 수행하기 위한 핵심은 ID를 반환하는 $interval 서비스를 사용하는 것입니다.

$scope.intervalId = $interval(retryMessage, 1000);

그러면 설정한 조건에 따라 취소가 가능합니다.

저는 당신이 이루고자 하는 것을 보여주는 plnkr을 만들었습니다.

http://plnkr.co/edit/RmADu1aiOUO5o4k4pnqE?p=preview

저는 최근에 이 타이머를 썼는데, 이 타이머에서 여러분은 어떤 논리를 취할 수 있을지도 모릅니다 - 플렁커.카운트 업 되어 정해진 시간에 끝날 수 있습니다.

JS

(function() {

    'use strict';

    var angularTimerApp = angular.module('angularTimerApp', []);

    angularTimerApp.directive("angularTimer", function() {
        return {
            restrict: "E",
            templateUrl: "angular-timer.html",
            scope: {endTime: "@"},
            controllerAs: "at",
            bindToController: true,
            controller: ["$scope", "$interval", function ($scope, $interval) {
                var at = this;
                at.secondsInAYear = 31536000;
                at.secondsInADay = 86400;
                at.secondsInAnHour = 3600;
                at.secondsInAMinute = 60;
                at.endTimeValue = null;

                $scope.$watch("at.endTime", function(newValue) {
                  if (angular.isDefined(newValue)) {
                    at.endTimeValue = parseInt(newValue); // No test for int
                  }
                });

                at.getTimeDisplay = function(seconds) {
                    var hoursTxt = Math.floor(((seconds % at.secondsInAYear) % at.secondsInADay) / at.secondsInAnHour);
                    var minutesTxt = Math.floor((((seconds % at.secondsInAYear) % at.secondsInADay) % at.secondsInAnHour) / at.secondsInAMinute);
                    var secondsTxt = (((seconds % at.secondsInAYear) % at.secondsInADay) % at.secondsInAnHour) % at.secondsInAMinute;
                    return ("Hours: " + hoursTxt + ", Minutes: " + minutesTxt + ", Seconds: " + secondsTxt);
                };

                at.reset = function () {
                    at.timeOffset = 0;
                    at.timeDisplay = at.getTimeDisplay(0);
                };
                at.reset();

                at.stop = function () {
                    $interval.cancel(at.timer);
                    at.timeOffset = at.time;
                };

                at.start = function() {
                    at.timeStart = (new Date()).getTime();

                    at.timer = $interval(function() {
                        at.time = Math.floor(((new Date()).getTime() - at.timeStart) / 1000) + at.timeOffset;
                        if ((at.endTimeSet) && (at.endTimeValue !== null)) {
                            if (at.time > at.endTimeValue) {
                                at.stop();
                            }
                            else {
                                at.timeDisplay = at.getTimeDisplay(at.time);
                            }
                        }
                        else {
                            at.timeDisplay = at.getTimeDisplay(at.time);
                        }
                    }, 1000);
                };
            }]
        };
    });
})();

마크업

<body>
    <angular-timer end-time="10"></angular-timer>
</body>

각침이 있는

{{at.timeDisplay}}
<br><br>
<button ng-click="at.start()">Start</button>
<br><br>
<button ng-click="at.stop()">Stop</button>
<br><br>
<button ng-click="at.reset()">Reset</button>
<br><br>
<input type="checkbox" ng-model="at.endTimeSet"> End at 27 seconds

당신이 정말 원하는 것은 당신의 컨트롤러로 알림을 다시 보내주는 약속, 즉 약속을 돌려주는 서비스라고 생각합니다.다음은 이러한 서비스의 예입니다.

<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@1.4.0-rc.0" data-semver="1.4.0-rc.0" src="https://code.angularjs.org/1.4.0-rc.0/angular.js"></script>
</head>
<body ng-app="myapp" ng-controller="main">

<h1>Task Retry Example</h1>
<p>Task condition: {{value}}</p>
<button ng-click="value = true">Set task condition to true</button>
<button ng-click="reset()">Reset Task</button>
<p>{{msg}}</p>

<script>
  var app = angular.module('myapp', []);
  app.controller('main', function($scope, task){
    var myTask = function(){
      return $scope.value;
    }

    function success(result){
      $scope.msg = result;
    }
    function failure(reason){
      $scope.msg = reason;
    }
    function notify(value){
      $scope.msg = value.message;
    }

    $scope.reset = function(){
      $scope.value = false;
      $scope.msg = "Loading...";
      task.go(myTask, {maxAttempts: 3, waitTime: 3})
        .then(success, failure, notify);
    }

    $scope.reset();

  });

  app.service('task', function($q, $timeout){

    var DEFAULT_OPTIONS = {
      maxAttempts: 1,
      waitTime: 10
    };
    var thisOptions = {};

    function _countDownStep(secondsLeft, attemptsLeft, countDownProgress, taskAttemptProgress){
      if(secondsLeft <= 0){
        countDownProgress.resolve(true);
        return;
      }
      var attempt = thisOptions.maxAttempts - attemptsLeft,
            msg = "Attempt failed; retrying (" + attempt + " of " + thisOptions.maxAttempts + ") in " + secondsLeft + " seconds...";
      taskAttemptProgress.notify({
        "state": "WAITING",
        "message": msg
      })
      $timeout(function(){
        _countDownStep(secondsLeft-1, attemptsLeft, countDownProgress, taskAttemptProgress);
      }, 1000);
    }

    function _countDown(secondsLeft, attemptsLeft, progress){
      var deferred = $q.defer();
      _countDownStep(secondsLeft, attemptsLeft, deferred, progress);
      return deferred.promise;
    }

    function _attempt(task, attemptsLeft, progress){
      if(!angular.isFunction(task)) {
        progress.reject("Task is not a function.");
        return;
      }
      if(attemptsLeft <= 0){
        progress.reject("Max attempts reached.");
      }
      var result = task();
      if(result){
        progress.resolve("Successfully completed task.");
      }else {
        --attemptsLeft;
        if(attemptsLeft <= 0){
          progress.reject("Max attempts reached.");
        }
        _countDown(thisOptions.waitTime, attemptsLeft, progress).then(function(){
          var attempt = thisOptions.maxAttempts - attemptsLeft,
            msg = "Making another attempt (" + attempt + " of " + thisOptions.maxAttempts + ")...";
          progress.notify({
            "state": "TRYING",
            "message": msg
          })
          _attempt(task, attemptsLeft, progress);  
        });
      }
    }

    function _go(task, options){
      var deferred = $q.defer();
      thisOptions = options || DEFAULT_OPTIONS;
      _attempt(task, thisOptions.maxAttempts, deferred);
      return deferred.promise;
    }

    return {
      go: _go
    }

  });

</script>

언급URL : https://stackoverflow.com/questions/29689254/how-can-i-show-a-message-counting-down-every-one-second-with-angularjs

반응형