I have code that I use to check a connection to the server. My code runs every 60 seconds. Once the code has run then it creates a message and this shows up on a page. Here's what I have so far:
The code that checks:
$interval(function () { us.isConnected().then(closeConnect, openConnect); }, 60 * 1000);
The code that does the check
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; };
What I would like to do is to have a simple function called retryMessage() that will allow me to give a message like this:
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.
With the number of seconds counting down until 0 when there will be a recheck.
Can anyone suggest a way in AngularJS that I can achieve this countdown?
One possible way of doing what you're attempting is to use $q.notify
in conjunction with $interval
.
Other messages can be passed with the resolve and reject. Of course, any place this is done you could just print straight to a logging service instead, but I thought it might be appropriate to return these messages with the promise behaviours (where, if you wanted, you could even instead return an object complete with status code and other data along with the message).
In the below sample, I've let the controller manage the logging and limited its output to 12 lines. I've also specified parameters for the connection testing so it attempts to connect every 60 seconds, 20 times (these params could be changed to attempt at different intervals, a different amount of times, or indefinitely). If the test is a failure, it prints the retry message(s) every second until the retry attempt:
(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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With