Как сделать l oop через список строк и одновременно уменьшить скорость зацикливания в js? - PullRequest
1 голос
/ 26 февраля 2020

Я хочу создать javascript, который повторяет все имена и всегда отображает текущее имя l oop в пользовательском интерфейсе (html). Но в то же время скорость l oop должна уменьшиться.

Допустим, мы начинаем со скоростью 10 циклов в секунду. Затем он должен уменьшиться до 1 л oop / сек, а затем остановиться в этой точке и отобразить имя. Это своего рода лотерея, и победитель должен быть случайным.

Итак, я создал сценарий ниже, но проблема в том, что ничего не происходит? Как-то просто ничего не происходит. Он выполняет код, но без ошибок и ничего не меняется в пользовательском интерфейсе. Код выполняется (проверяется при входе в консоль)!

Моя функция:

function Roll(){
    var delay = 100;
    for(var i = 0; delay < 1000; i++){
        delay += 25;
        if(i >= listOfParticipants.length){
            i = 0;
        }
        setTimeout(function() {
            document.getElementById("person_name").value = listOfParticipants[i];
        }, delay);
    }
}

элемент html:

<h1 class="text-center mt-2" id="person_name" ></h1>

РЕДАКТИРОВАТЬ: Я думаю, что я знаю, в чем проблема, но я не знаю, как ее решить. Я думаю, что для l oop не ждет, пока setTimeout завершится sh. Не знаю, как с этим справиться.

РЕДАКТИРОВАТЬ 2: Кажется, что setTimeout создает новый ExecutionContext. Это означает, что for-l oop заканчивается и получает свое максимальное значение (13) до того, как setTimeout будет выполнен. Теперь вопрос заключается в том, как добавить тайм-аут в текущий ExecutionContext? В списке всего 12 объектов, поэтому результат с i = 13 не определен.

Ответы [ 2 ]

2 голосов
/ 26 февраля 2020

Предполагая, что вы хотите остановиться на фамилии массива (поскольку в вашем вопросе неясно, как должен работать выбор имени), есть стратегия, которую вы можете использовать.

По сути, вместо того, чтобы перебирать продолжительность, вы хотите l oop через ваш массив listOfParticipants. На каждой итерации мы уменьшаем продолжительность ожидания, прежде чем перейти к следующей итерации для l oop.

// Pseudo code!
async function roll() {
  for (let i = 0; i < listOfParticipants.length; i++) {
    // Wait for promise to resolve
    await someKindOfPromise();

    // Update name
    document.getElementById('person_name').innerText = listOfParticipants[i];
  }
}

. Это можно сделать с помощью async / await . Натив для l oop в ES6 поддерживает ожидание обещания, поэтому мы просто создаем метод, который возвращает обещание, которое разрешается через x количество секунд:

// A simple promise that resolves after a specified duration
function wait(duration) {
  return new Promise(resolve => {
    window.setTimeout(resolve, duration);
  });
}

После x числа вторые проходы, мы переходим к следующей итерации.

Значение x может быть просто определено путем уменьшения предварительно установленной длительности на основе нашего относительного положения вдоль массива участников. Чем дальше вы находитесь в массиве (указан индексом i), тем короче вы хотите, чтобы время было, например: delay * i / listOfParticipants.length;

async function roll() {
  const delay = 100;
  for (let i = 0; i < listOfParticipants.length; i++) {
    // Force the for loop to wait for a set amount of time
    const duration = delay * i / listOfParticipants.length;
    await wait(duration);

    // Once the duration has been awaited, we can then update the inner text
    document.getElementById('person_name').innerText = listOfParticipants[i];
  }
}

См. Подтверждение концепции ниже:

const listOfParticipants = ['Adena', 'Socorro', 'Germaine', 'Ebony', 'Raul', 'Anton', 'Rochel', 'Morgan', 'Joanie', 'Ellsworth', 'Edelmira', 'Susannah', 'Gino', 'Vicenta', 'Katrina', 'Devorah', 'Olinda', 'Lise', 'Napoleon', 'Dessie', 'Herta', 'Cassaundra', 'Nadine', 'Dalton', 'Mica', 'Haydee', 'Linh', 'Williemae', 'Desiree', 'Philomena', 'Julio', 'Darell', 'Shana', 'Ligia', 'Melita', 'Laurene', 'Darby', 'Gregg', 'Shemika', 'Tesha', 'Benita', 'Hyman', 'Kattie', 'Mary', 'Julienne', 'Claud', 'Heather', 'Toney', 'Vasiliki', 'Stephani', 'Violette', 'Barney', 'Warren', 'Felix', 'Mathew', 'Blair', 'Jamar', 'Grover', 'Bud', 'Barbie', 'Gina'];

// A simple promise that resolves after a specified duration
function wait(duration) {
  return new Promise(resolve => {
    window.setTimeout(resolve, duration);
  });
}

async function roll() {
  const delay = 100;
  for (let i = 0; i < listOfParticipants.length; i++) {
    // Force the for loop to wait for a set amount of time
    const duration = delay * i / listOfParticipants.length;
    await wait(duration);
    
    // Once the duration has been awaited, we can then update the inner text
    document.getElementById('person_name').innerText = listOfParticipants[i];
  }
}

document.querySelector('#btn').addEventListener('click', () => roll());
<h1 class="text-center mt-2" id="person_name"></h1>
<button id="btn">Raffle</button>
1 голос
/ 26 февраля 2020

Вместо использования al oop вы можете вызвать setTimeout() рекурсивно:

<h1 class="text-center mt-2" id="person_name" ></h1>
var listOfParticipants = [
  "Kurt",
  "Dave",
  "Krist",
  "Alanis",
  "Aimee",
  "Chris",
  "Eddie",
  "Mike",
  "Stone",
  "Jeff",
  "Matt",
  "Boom"
]

function doIt(i) {
  var participant = listOfParticipants[i];
  if (!participant) return;

  document.getElementById("person_name").innerHTML = participant;
  setTimeout(
    function() { 
      doIt(i + 1);
    }, 
    100 + i * 100
  );
}

doIt(0);
...