SetTimeout inside SetTimeout not working

I am trying to create a button that gives a link back to the action that it performs. In Angular, I make a request for a request to the server - at this moment I change the state of the button to indicate this - then when I get a response, I again change the state of the button to reflect success or failure for 1.5 seconds, and then reset, he returned to what was originally before the button was pressed. Also at this moment a message is displayed reflecting success or failure, and after another 5 seconds an additional action should be performed. The displayed message should be hidden if it is an error, and the page should be redirected if it was successful. This is the last part that I do not work with.

So my question is, should I put setTimeout inside another setTimeout?

Here is my code (inside the function for the button):

$scope.resetPassword = function() {

    $scope.ShowSuccessMessage = false;
    $scope.ShowFailedMessage = false;

    var querystring = $location.search();

    var dataObject = { email1 : $scope.formEmail1, email2 : $scope.formEmail2, password1: $scope.formPassword1, password2: $scope.formPassword2, token: querystring.token };

    var responsePromise = $http.put("/myurl/", dataObject, {});

    //  change colour and icon of reset button for 1.5 sec
    var $el           = $("#resetPassword");
    var resetButton   = 1500;
    var resetMessage  = 5000;
    var originalColor = $el.css("background");
    var originalIcon  = $el[0].firstChild.className; // get first html element in the button, which is the <i>

    $el[0].firstChild.className = "fa fa-circle-o-notch fa-spin";

    responsePromise.success(function(dataFromServer, status, headers, config) {
      $el.css("background", "#02c66c");
      $el[0].firstChild.className = "fa fa-check-circle";

      $scope.ShowSuccessMessage = true;

      ResetButton($el, $scope, originalColor, originalIcon, resetButton, true, resetMessage);
    });

    responsePromise.error(function(dataFromServer, status, headers, config) {
      $el.css("background", "#d9534f");
      $el[0].firstChild.className = "fa fa-times-circle";

      $scope.ShowFailedMessage = true;

      ResetButton($el, $scope, originalColor, originalIcon, resetButton, false, resetMessage);
    });
};

ResetButton = function(el, scope, originalColor, originalIcon, resetButton, success, resetMessage)
{
  setTimeout(function() {
    el.css("background", originalColor);
    el[0].firstChild.className = originalIcon;

    ChangeMessageOrChangeLocation(scope, success, resetMessage);
  }, resetButton);
}

ChangeMessageOrChangeLocation = function(scope, success, resetMessage)
{
  if(success) {
    setTimeout(function(){
      window.location = '/signin';
    }, resetMessage);
  }
  else {  
    setTimeout(function() {
      scope.ShowFailedMessage = false;
    }, resetMessage);
  }
}

EDIT: Here's a living example: Greedy Magpie (Keep in mind that this is a work in progress, so not everything on the site will work.) Just click the password reset button ...

+4
source share
1 answer

winfow.setTimeout runs outside the Angular digest loop, so the view is not updated. Either add scope.$apply()after scope.ShowFailedMessage = false;, or use the service $timeoutinstead of setTimeout. The second approach is better.

Check the $ timeout service documentation here: $ timeout

+1
source

All Articles