setTimeout no nó.ciclo js
setTimeout
funciona. 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
6 answers
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.
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;)
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.
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 ()
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)
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.