как остановить рекурсию setTimeout - PullRequest
0 голосов
/ 14 мая 2019

Я создал setTimeout с обратным вызовом с именем run. Внутри прогона я вызвал console.log(i), чтобы вывести значение I с помощью i++, и как только оно достигнет 50, я хочу очистить setTimeoutс clearTimeout я снова вызываю setTimeout с помощью run, что делает его рекурсивным, но это не работает.Может ли кто-нибудь помочь мне лучше понять концепцию?

let i = 1;

var abc = setTimeout(function run(){
   console.log(i);
if(i==50){
    abc1();
  }  
  i++;
  setTimeout(run,100);
},100);
function abc1(){
     clearTimeout(abc);
}

Ответы [ 7 ]

1 голос
/ 14 мая 2019
let i = 1;

var abc = setTimeout(function run(){
  console.log(i);
  if(i<50){
      setTimeout(run,100);
    }  
  i++;

},100);

Вы должны запустить тайм-аут, только если таймер не истек.

1 голос
/ 14 мая 2019

Когда вы звоните setTimeout, вы получаете идентификатор возвращенного таймера. Это именно то, что вы сделали здесь:

var abc = setTimeout(function run(){

Однако этот идентификатор действителен только до тех пор, пока не будет запущена отложенная функция. Как только это произойдет, это неэффективно. Когда вы звоните setTimeout(run,100);, вы получите новый идентификатор для таймера. Вам нужно снова это зафиксировать, иначе идентификатор будет утерян, и у вас нет возможности его остановить.

Существует последнее соображение - с вашим текущим кодом, даже если вы должны были правильно захватить идентификатор, вызывающий abc = setTimeout(run, 100);, который все равно не остановил бы счетчик, потому что он попытается остановить функцию, которая работает прямо сейчас (которая ничего не делает ) вместо отмены выполнения следующего:

let i = 1;

var abc = setTimeout(function run() {
  console.log(i);
  if (i == 50) {
    abc1(); //this will clear the *current* timer 
  } 
  i++;
  abc = setTimeout(run, 100); //this will set the *new* ID 

}, 100);

function abc1() {
  clearTimeout(abc);
}

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

let i = 1;

var abc = setTimeout(function run() {
  console.log(i);
  abc = setTimeout(run, 100); //this will set the *new* ID 
  if (i == 50) {
    abc1(); //this will clear the *new* timer now
  }
  i++;
}, 100);

function abc1() {
  clearTimeout(abc);
}

В качестве альтернативы, вы можете сделать это вообще без ручек таймера и просто использовать условие if, чтобы определить, хотите ли вы запланировать другое выполнение или нет:

let i = 1;

setTimeout(function run() {
  console.log(i);
  if (i != 50) { //until 50 is reached
    abc = setTimeout(run, 100); //schedule a new execution
  }
  i++;
}, 100);
1 голос
/ 14 мая 2019

Проблема в порядке ваших операций.

if(i==50){
    abc1();
  } 

Если я достигну 50, будет вызвана функция abc1 (), которая очищает интервал.

i++;
setTimeout(run,100);

здесь вы перезапускаете интервал. Вам нужно обернуть его внутри блока else.

let i = 1;

var abc = setTimeout(function run() {
  console.log(i);
  if (i == 50) {
    abc1();
  } else {
    i++;
    setTimeout(run, 100);
  }
}, 100);

function abc1() {
  clearTimeout(abc);
}
0 голосов
/ 14 мая 2019

вам нужно добавить return после вызова функции abc1.Вы сбрасываете тайм-аут, но затем код все еще работает и снова вызываете setTimeout (run, 100).

        let i = 1;

var abc = setTimeout(function run(){
   console.log(i);
if(i==50){
    abc1();
    return;
  }  
  i++;
  setTimeout(run,100);
},100);
function abc1(){
     clearTimeout(abc);
}
0 голосов
/ 14 мая 2019

Это странный способ сделать синхронизированный цикл, но вам просто нужно очистить (на самом деле, не в этом случае, но мне нравится делать это в любом случае, так как это хорошая практика освобождать ресурсы, если вы больше их не используете)таймауты (выполняемые путем отслеживания дескриптора abc) до создания новых и возврата после clear при заданном условии:

let i = 1;

let abc = setTimeout(
  function run(){
    console.log(i);
    if(i==50){
      abc1();
      return;
    }
    abc1();
    i++;
    abc = setTimeout(run,100);
  },
  100
);

function abc1(){
  clearTimeout(abc);
}
0 голосов
/ 14 мая 2019

Поскольку var abc устанавливается только один раз, при первом тайм-ауте вы удаляете только самый первый тайм-аут, который, скорее всего, уже завершен.

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

Если вы хотите очистить последний тайм-аут, возможно, вы бы хотели всегда обновлять abc идентификаторами для каждого тайм-аута, например:

 abc = setTimeout(run,100);
0 голосов
/ 14 мая 2019

setTimeout () внутри run () не назначен ни одной переменной, поэтому он не может быть очищен каким-либо образом.

Полагаю, вы хотите перезаписать abc, поэтому вы должны заменить:

setTimeout(run,100);

от

abc = setTimeout(run,100);
...