Javascript array.forEach (function) выполняет функцию в два раза больше, чем ожидалось

1

У меня есть html файл с одной кнопкой на нем

<!DOCTYPE html>
<html>    <body>
<p>Click the button to list all the items in the array.</p>

<button onclick = "numbers.forEach(myFunction)" >Try it</button>

<p id="demo"></p>
</body>     
</html>

У меня также есть файл Javascript, содержащий функцию onclick для метода .forEach.
Когда нажимается кнопка, я бы хотел пройти через массив, перейдя через каждый экземпляр элемента в массиве.

Для каждого элемента в этом массиве я хотел бы распечатать его индекс и значение с последующим таймером, который ждет вторую, чтобы отобразить следующую перестановку.

demoP = document.getElementById("demo");
var numbers = [];

var random = Math.floor(Math.random() * 4) + 1;

numbers.push(random);

function myFunction(item, index) {
  random = Math.floor(Math.random() * 4) + 1;
  numbers.push(random);
  demoP.innerHTML = demoP.innerHTML + "numbers[" + index + "]: " + item + "<br>"; 
  //demoP.innerHTML = demoP.innerHTML + "<br>" //add magic spacing between permutation
  sleep(100);
  //switch to this and see how slow?
  //sleep(1000);
}

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

Что бы я хотел, чтобы результат показывал, когда пользователь нажимает кнопку:

numbers[0] = 4
//waits a second and adds a <br> here to separate
numbers[0] = 4
numbers[1] = 2
//waits a second and adds a <br> here
numbers[0] = 4
numbers[1] = 2
numbers[2] = 3

и так далее.

В настоящее время код выводит как минимум в два раза больше элементов, а sleep(), по-видимому, длится дольше, чем нужно.

  • 4
    Пожалуйста, не пытайтесь добавить функцию sleep . Вместо этого узнайте, как выполнять асинхронные вызовы через что-то вроде setTimeout или setInterval . Также рассмотрите возможность использования console.log для отслеживания вашего кода во время его работы. А так как вы меняете numbers массивов при выполнении forEach вы просите о проблемах. И делать forEach в атрибуте onclick элемента DOM - не лучший способ. Сделайте так, чтобы onclick вызывал функцию и выполнял forEach в этой функции.
  • 0
    @Intervalia У меня были проблемы с количеством интервалов, поэтому вместо использования 'setTimeout' или 'setInterval' я создал 'sleep ()' для его проверки.
Показать ещё 1 комментарий
Теги:
arrays
foreach
sleep

1 ответ

4
Лучший ответ

Помимо отвратительной функции sleep. Вы используете myFunction как обратный вызов forEach, а в myFunction вы нажимаете новые элементы на numbers которые являются тем же самым массивом, который вы вызываете для forEach.

forEach не будет вызывать обратный вызов для вновь выдвинутых элементов, все еще продолжая цикл массива. Но к концу цикла элементы в массиве будут удвоены. Как указано в MDN:

Диапазон элементов, обработанных forEach(), устанавливается перед первым вызовом callback. Элементы, которые добавляются в массив после вызова forEach(), не будут посещаться callback.

Если массив содержит N элементов, то при щелчке будет показано N элементов, а myFunction будет нажимать N других элементов, а когда следующий щелчок произойдет, на этот раз будут показаны 2N элементы,...

Поэтому после каждого щелчка элементы в массиве будут удвоены.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню