Для Loop SetTimeout работает только 1 раз - PullRequest
0 голосов
/ 13 октября 2019

У меня есть кнопка с функцией щелчка ниже. Он имеет 3 вложенных цикла и 1 функцию setTimeout.

Приведенные ниже циклы повторяются 5 раз. Я хочу, чтобы приведенный ниже код работал (5x5) всего 25 секунд времени выполнения, и каждые 5 секунд вывод на консоль должен быть напечатан «Ожидание».

Однако приведенный ниже код работает только 5 секунд и сразу выводит «5 привет». Без изменения структуры цикла for, как я могу заставить ее работать так, как я хочу?

  jQuery("#btn_trendyolStocksSYNC").click(function() {
    for(var product in all){
      var colors = all[product];
      for(var singleColor in colors[0]){
        var size = colors[0][singleColor];
        for(var index in size){
          var singleSize = size[index];
          setTimeout(function (){
            console.log('Waited');
          }, 5000);
        }
      }
    }
  });

Редактировать: я не использую цикл for с индексами, поэтому решения для числа, индексированного для циклов, не работают дляя.

Ответы [ 3 ]

2 голосов
/ 13 октября 2019

Вы можете попытаться, добавив await и Promise:

jQuery("#btn_trendyolStocksSYNC").click(async function() {
    for(var product in all){
      var colors = all[product];
      for(var singleColor in colors[0]){
        var size = colors[0][singleColor];
        for(var index in size){
          var singleSize = size[index];
          await new Promise(resolve => setTimeout(function (){
            console.log('Waited');
            resolve();
          }, 5000));
        }
      }
    }
});

Это просто скажет вашему циклу остановиться и продолжить только после того, как объект Promise вызовет свою функцию параметра resolve,Таким образом, ваша задержка должна произойти до следующей итерации. Это важный код:

await new Promise(resolve => setTimeout(function (){
      console.log('Waited');
      resolve();
}, 5000));

Он просто создает Promise, который мы будем разрешать, как только тайм-аут пропустит 5000 миллисекунд. Затем мы говорим нашему циклу просто дождаться этого завершения, прежде чем перейти к следующему элементу.

Примечание Вам также необходимо добавить async в вашу функцию-обработчик, чтобы javascript знал, что эта функция можетподожди и возьми столько, сколько нужно.

1 голос
/ 13 октября 2019

Функция setTimeout(); является асинхронной , что означает, что ваш сценарий не будет ждать его завершения, прежде чем двигаться дальше. Вот почему он имеет обратный вызов.

Попробуйте что-то вроде этого: (не самый лучший метод)

//delayed loop
var i = 1;
function loop() {
    //wait 5 secs
    setTimeout(function() {
        console.log(i);
        if(i>5) {
            //cancel
            return;
        }
        loop();
        i++;
        return;
    }, 1000);
    if(i>5) {
        //cancel function
        return;
    }
}
//do the loop
loop();

Как и то, что здесь сказано, вы можете поместить setTimeout в оператор if.

Конечно, чтобы сделать что-то после окончания цикла, вам нужна функция обратного вызова.

0 голосов
/ 14 октября 2019

Вы можете использовать setInterval и clearInterval.

var n=0;
var a = setInterval(()=>{
    console.log("Waited");
    n++; if(n==5){clearInterval(a);}
},5000);
...