setTimeout no nó.ciclo js

Estou um pouco confuso sobre como setTimeoutfunciona. Estou a tentar ter uma repetição, para que as iterações estejam, digamos, separadas. Cada iteração de loop faz um pedido HTTP e parece que o servidor na outra extremidade não pode lidar com que muitos pedidos em um período de tempo tão curto.

for (var i = 1; i<=2000 && ok; i++) {
    var options = {
        host:'www.host.com',
        path:'/path/'+i
    };

    setTimeout(makeRequest(options, i), 1000);
};
Porque é que isto não funciona e como é que eu consigo?

Obrigado

Author: Yves M., 2013-03-28

6 answers

Precisas de algo assim.
var counter = 5;

function makeRequst(options, i) {
    // do your request here
}

function myFunction() {
    alert(counter);

    // create options object here
    //var options = {
    //    host:'www.host.com',
    //    path:'/path/'+counter
    //};
    //makeRequest(options, counter);

    counter--;
    if (counter > 0) {
        setTimeout(myFunction, 1000);    
    }
}

Ver também este violino

No ponto do alert(count); você pode fazer a sua chamada para o servidor. Note que o contador funciona em frente (contagem decrescente). Eu atualizei com alguns comentários sobre onde fazer a tua coisa.

 6
Author: bart s, 2013-03-28 13:18:54

SetTimeout is non blocking, it is asynchronous. Liga-lhe e quando o atraso acabar, chama-se.

Aqui estão algumas implementações:

Usando recursão

Pode usar uma chamada recursiva na chamada setTimeout.

function waitAndDo(times) {
  if(times < 1) {
    return;
  }

  setTimeout(function() {

    // Do something here
    console.log('Doing a request');

    waitAndDo(times-1);
  }, 1000);
}

Aqui está como usar a sua função:

waitAndDo(2000); // Do it 2000 times

Acerca dos erros de sobreposição da pilha: setTimeout limpar a pilha de chamadas (ver esta pergunta ) para que não tenha para se preocupar com o excesso de pilha em chamadas recursivas.

Utilizando geradores (io.js, ES6)

Se já estiver a utilizar io.js (o nó "próximo".js que usa ES6), você pode resolver o seu problema sem recursão com uma solução elegante:

function* waitAndDo(times) {
  for(var i=0; i<times; i++) {

    // Sleep
    yield function(callback) {
      setTimeout(callback, 1000);
    }    

    // Do something here
    console.log('Doing a request');
  }
}

Aqui está como usar a sua função (com co):

var co = require('co');

co(function* () {
  yield waitAndDo(10);
});

BTW: isto é realmente usar um laço;)

Documentação sobre as funções geradoras.

 11
Author: Yves M., 2017-05-23 11:54:51
Neste momento, estás a agendar todos os teus pedidos para acontecer ao mesmo tempo, só um segundo depois do guião ser executado. Você terá que fazer algo como o seguinte:
var numRequests = 2000,
    cur = 1;

function scheduleRequest() {
    if (cur > numRequests) return;

    makeRequest({
        host: 'www.host.com',
        path: '/path/' + cur
    }, cur);

    cur++;
    setTimeout(scheduleRequest, 1000)
}

Note-se que cada pedido subsequente só está agendado depois de o actual estar completo.

 3
Author: jmar777, 2013-03-28 13:21:32

Você está chamando makeRequest () na sua chamada setTimeout-você deve estar passando a função para setTimeout, não chamá - lo, então algo como

setTimeout(makeRequest, 1000);

Sem o ()

 1
Author: Evan Knowles, 2013-03-28 13:05:22
Estou surpreso que ninguém tenha mencionado isso acima, mas parece que você precisa de setInterval não setTimeout.
vat poller = setInterval(makeRequestFunc, 3000)

O código acima fará um pedido a cada 3 segundos. Uma vez que guardou o objecto para a variável poller, poderá parar a sondagem limpando o objecto assim:

cleanInterval(poller)
 1
Author: Sean, 2018-03-13 23:53:57

Posso chegar atrasado à festa, mas aqui está outra solução (mais legível) sem a necessidade de omitir {[[1]} loop.

O que o seu código faz é criar 2000 (na verdade, 1999) setTimeout objectos que irão chamar a função makeRequest após 1 segundo a partir de Agora. Nenhum deles sabe da existência dos outros setTimeout. Se os queres a um segundo de distância um do outro, és responsável por criá-los assim.

Isto pode ser conseguido usando o seu contador (neste caso i) e o tempo de espera atraso.

for (var i = 1; i<=2000 && ok; i++) {
    var options = {
        host:'www.host.com',
        path:'/path/'+i
    };

    setTimeout(makeRequest(options, i), i * 1000); //Note i * 1000
};

O primeiro tempo limite objeto será definido por 1 segundo a partir de agora e a segunda vai ser definido por 2 segundos a partir de agora e assim por diante; ou seja,1 segunda afastados uns dos outros.

 0
Author: Ahmad Maleki, 2017-05-08 06:50:42