Como alterar o tempo do intervalo dinamicamente no loop for de acordo com o número de índice / iteração?

12

Como não pude comentar, sou forçado a escrever este post. Eu recebi o código abaixo que atrasa / espera exatamente 1 segundos ou 1000 milissegundos -

let n = 5;
for (let i=1; i<n; i++)
{
  setTimeout( function timer()
  {
      console.log("hello world");
  }, i*1000 );
}

Mas como posso atrasá-lo * 1000 segundos em vez de 1000 milissegundos fixos, para que a espera dependa do número da iteração?

Por exemplo, se n = 5, quero o atraso do loop 1 segundo na 1ª iteração. 2 segundos na segunda iteração e assim por diante .. o atraso final será de 5 segundos.

Mike
fonte
2
Então você quer fazer 9 temporizadores? Nesse caso, seu código fará o que você está pedindo. Não espera exatamente 3 segundos. De fato, os temporizadores nunca serão exatos.
Scott Marcus
11
sua pergunta não faz sentido #
4119 DanStarns
2
Apenas tentei seu código em um codepen: codepen.io/Connum/pen/BaaBMwW Você recebe 9 mensagens a 3000ms de distância - se não é isso que você deseja (mas da sua pergunta soa como é), especifique qual é o resultado pretendido é.
Constantin Groß
11
Você não parecem compreender como setTimeout funciona em primeiro lugar - é não um “atraso”. No momento, você está recebendo seus alertas em intervalos de 3 segundos, porque você já multiplicou o 3000 por i- se não o fizesse, obteria todos esses alertas ao mesmo tempo.
04FS 04/04/19
3
Editar a pergunta para deixar sua última frase em negrito não está realmente ajudando o seu caso. Você já foi informado por vários comentaristas que seu código já faz o que você está solicitando (ou melhor, não está muito claro o que você está realmente pedindo, se esse não é o resultado pretendido).
Constantin Groß

Respostas:

6

Aqui está uma função que será exibida imediatamente, depois 1 segundo depois, 2 segundos depois, 3 segundos depois etc. Nenhuma matemática especial, nenhuma promessa necessária

const n = 5;
let cnt=0;

function show() {
  console.log("call "+cnt,"delay: ",cnt,"sec");
  cnt++;
  if (cnt > n) return; // we are done
  setTimeout(show, cnt*1000 ); // cnt seconds later
}
show()

mplungjan
fonte
11
Lamento muito por ter perdido sua resposta, houve tantos comentários, mal-entendidos, respostas ... de qualquer forma, estou escolhendo sua resposta, pois você foi a primeira pessoa a resolver o que pedi graças pelo seu tempo, senhor.
Mike
@Mike Lol. As outras soluções são úteis em seu próprio direito, por isso obrigado pelo aceitar
mplungjan
Pavan é o mesmo na sintaxe ES6. Mais difícil de ler, mas é de fato o mesmo. Sua edição para torná-lo assim foi feito ao mesmo tempo como eu escrevi o meu :)
mplungjan
8

Embora essa tarefa possa ser resolvida com promessas, fluxos reativos e outras ferramentas interessantes (ei, ninguém sugeriu o uso de trabalhadores ainda!), Ela também pode ser resolvida com um pouco de aritmética.

Portanto, você deseja tempos limite em uma sequência: 1s, o anterior + 2s, o anterior + 3s e assim por diante. Esta sequência é: 1, 3, 6, 10, 15 ... e sua fórmula é a[n] = n * (n + 1) / 2. Sabendo que...

let n = 6;
console.log(new Date().getSeconds());

for (let i = 1; i < n; i++) {
  setTimeout(function timer() {
    console.log(new Date().getSeconds());
  }, 1000 * i * (i + 1) / 2);
}

mbojko
fonte
Os matemáticos ainda estão vivos !! :)
Bilal Siddiqui
5

Você pode tentar usar async / waitit (Promises), para serializar seu código:

const waitSeconds = seconds => new Promise(resolve => setTimeout(resolve, seconds))

async function main () {
 let oldDate = new Date()
 let newDate
 
 /* 
  * If you put 'await' inside the loop you can synchronize the async code, and simulate
  * a sleep function
  */
 for (let i=1; i<5; i++) {
    await waitSeconds(i*1000)
    newDate = new Date()   
    console.log(`Loop for i=${i}, elapsed=${moment(newDate).diff(oldDate, 'seconds')} seconds`)
    oldDate = newDate
 }
 
 console.log('End')
}

main()
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

Mauro Stepanoski
fonte
5

Levei algum tempo para decifrar sua pergunta xD, mas é isso que você quer?

Isso continuará disparando console.log com atraso de i * 1000 a cada vez. então, a primeira vez que durará 1 segundo (1 * 1000), a seguir, 2 segundos e assim por diante.

let i = 0;
loop = () => {
  setTimeout(() => {
    console.log(new Date()); // for clarity
    i++;
    if (i < 10) {
      loop();
    }
  }, i * 1000)
};
loop();

Pavan Skipo
fonte
Por exemplo, se n = 5, quero o atraso do loop 1 segundo na 1ª iteração. 2 segundos na segunda iteração e assim por diante .. o atraso final será de 5 segundos.
Mike
yup isso vai atrasar um segundo para o primeiro iteração, 2 segundos para 2 e assim por diante, experimentá-lo
Pavan Skipo
Sua descrição não corresponde ao código. Mas ele funciona
mplungjan 4/19/19
3

O loop não espera que a função de tempo limite seja concluída. Portanto, quando o loop é executado, ele agenda seu alerta para cada índice.

Você pode usar uma função que será executada de acordo com o seu índice, mas agendada ao mesmo tempo. Você pode sentir a diferença de 3 segundos.

function test(i){
    setTimeout( function timer(){
        console.log("hello world" + i);
    }, i*3000);
}
for (let i=1; i<4; i++) {
   test(i);
}
Bilal Siddiqui
fonte
3

Use chamadas recursivas em vez de loop for

let i=1;
function a(i) {
  if (i > 5)
    return
  else
    b("message", i)
}

function b(s, f) {
  setTimeout(function timer() {
    console.log(s + " " + f + " seconds");
  }, f * 1000);
  a(++i);
}
a(i);

elipse
fonte
Por exemplo, se n = 5, quero o atraso do loop 1 segundo na 1ª iteração. 2 segundos na segunda iteração e assim por diante .. o atraso final será de 5 segundos.
Mike