0

In it's simplest form my code is below, I am looping through an array and removing a random item in each iteration until the loop length is 0. I'd like to add a sleep or delay in each iteration but I'm not sure the best way to achieve this in angular1.x or plain js.

I have found this question What is the JavaScript version of sleep()? but can't get the top rated answer to work.

Can anyone please help with this:

while($scope.players.length > 0){

    random = Math.floor(Math.random() * $scope.players.length);
    $scope.players.splice(random, 1);

}
mark
  • 5
  • 6

5 Answers5

1

You can use setInterval for that purpose

The setInterval() method calls a function or evaluates an expression at specified intervals (in milliseconds).

The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.

The ID value returned by setInterval() is used as the parameter for the clearInterval() method.

Tip: 1000 ms = 1 second.

Tip: To execute a function only once, after a specified number of milliseconds, use the setTimeout() method.

Example

function _do(){
   if($scope.players.length > 0){

    random = Math.floor(Math.random() * $scope.players.length);
    $scope.players.splice(random, 1);

   } else clearInterval(_loop);
}

var _loop = setInterval(_do,1000); //Sleep for 1 sec
Nadir Laskar
  • 4,012
  • 2
  • 16
  • 33
0

You could use setInterval?

var array = [1, 2, 3, 4, 5, 6, 7]
var interval = null;


function removeArray() {
  random = Math.floor(Math.random() * array.length);
  array.splice(random, 1);
  console.log(array);

  if (array.length == 0) {
    clearInterval(interval);
  }
}

interval = setInterval(removeArray, 1000);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}
George
  • 6,630
  • 2
  • 29
  • 36
0

EDIT -> After a useful comment, I realize $timeout is not the best answer. So I'll agree with other answers here about using an interval, but I would still suggest using Angular's built-in $interval service:

(function() {
  'use strict';

  angular.module('MyApp', []);

  angular
    .module('MyApp')
    .controller('MyCtrl', MyCtrl);

  MyCtrl.$inject = ['$scope', '$interval'];

  function MyCtrl($scope, $interval) {

    $scope.players = ['a', 'b', 'c', 'd', 'e'];
    var INTERVAL_LENGTH = 1000; // This can be however long you want
    var INTERVAL_COUNT = $scope.players.length;

    if (INTERVAL_COUNT > 0) {
      $interval(function() {
        var random = Math.floor(Math.random() * $scope.players.length);
        $scope.players.splice(random, 1);
      }, INTERVAL_LENGTH, INTERVAL_COUNT).then(function() {
        $scope.players = 'done!';
      });
    }
  }
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="MyCtrl">
  <span>{{ players }}</span>
</div>

$interval also returns a promise which is resolved when the last iteration is complete, so any asynchronous work you want to do after the interval is complete can be easily handled.


Previous answer:

Angular provides the $timeout service. After injecting it as a dependency in your controller:

var PAUSE_AMOUNT = 500; // This can be however long you want
while($scope.players.length > 0){
    $timeout(function() {
        random = Math.floor(Math.random() * $scope.players.length);
        $scope.players.splice(random, 1);
    }, PAUSE_AMOUNT);
}

This will pause for 500 ms between each iteration of the while loop.

Gil Browdy
  • 69
  • 5
0

The SO answer you have mentioned in the question also works well. See the snippet.

var app = angular.module("MyApp", []).controller("MyCtrl", function($scope) {

  $scope.players = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd'];
  var ele = angular.element(document.querySelector('#playersEle'));
  ele.html($scope.players);
  function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  async function demo() {
    while ($scope.players.length > 0) {
      console.log('Taking a break...');
      await sleep(2000);
      console.log('Two second later');
      random = Math.floor(Math.random() * $scope.players.length);
      $scope.players.splice(random, 1);
      ele.html($scope.players);
    }
  }
  demo();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="MyApp" ng-controller="MyCtrl">
  <span id="playersEle"></span>
</body>
Sajal
  • 4,359
  • 1
  • 19
  • 39
0

Use the setInterval function.
This will keep calling the function after an amount of time. Example:

var myFunction = function () {
  //do something
};
setInterval(myFunction, 1000)

In this example it will call myFunction every 1000 mini seconds.
KEY:

1000 ms = 1 s

You can also cancel a setInterval with the script:

//create an variable for the setInterval
var intervalId = setInterval(myFunction, 2500);
//That is 2.5 seconds
//Now to cancel the interval:

clearInterval(intervalId);

Use the clearInterval(); to stop an interval. in the () put the interval name you want to stop.

CALLING MULTIPLE FUNCTIONS OR DO SOMETHING:

To call multiple functions at a time or do something else, use this:

var intervalId = setInterval(function () {
  //put whatever you want here, I'll put some examples
  callAFunction();
  inputFunction("123Example...");
  alert("Hello!"); 
  //Not a function, just as I said, you can do whatever you want here
  console.log("setInterval Is great"); //Not a function!!!!!!!!!!!!!
  //This is a comment
  /*
    This is
    another
  */
  functionCall();
  //here is the end of this variable
}, 100); //the number is the amount of ms after it loops again

You see? This is very useful!
Tell me if I said something you don't want to do.

^_^