Se você estiver familiarizado com a programação JavaScript do lado do cliente, pode ter usado as funções Settimeout e SetInterval, que permitem atrasos por um período antes de executar a função. Por exemplo, o código a seguir, uma vez carregado na página da web, após 1 segundo, "Olá" será adicionado após o documento da página:
A cópia do código é a seguinte:
var oneSecond = 1000 * 1; // Um segundo = 1000 x 1 ms
setTimeout (function () {
document.write ('<p> Olá. </p>');
}, OneSecond);
e o setInterval permite a execução repetida de funções em intervalos de tempo especificados. Se o código a seguir for injetado na página da web, fará com que a seguinte frase "olá" seja adicionada ao documento da página a cada segundo:
A cópia do código é a seguinte:
var oneSecond = 1000 * 1; // Um segundo = 1000 x 1 ms
setInterval (function () {
document.write ('<p> Olá. </p>');
}, OneSecond);
Como a Web se tornou uma plataforma para criar aplicativos, em vez de uma página estática simples, esse tipo de demanda semelhante está cada vez mais emergente. Essas funções de planejamento de tarefas ajudam os desenvolvedores a implementar a verificação periódica de formulários, atrasar a sincronização de dados remotos ou interações da interface do usuário que requerem respostas atrasadas. O nó também implementa esses métodos na íntegra. No lado do servidor, você pode usá -los para repetir ou atrasar a execução de muitas tarefas, como expiração do cache, limpeza do pool de conexões, expiração da sessão, pesquisa e muito mais.
Executar usando a função de atraso do settimeout
O setTimeout pode criar um plano de execução que execute a função especificada uma vez em um determinado momento no futuro, como:
A cópia do código é a seguinte:
var timeout_ms = 2000; // 2 segundos
var timeout = setTimeout (function () {
console.log ("Timed Out!");
}, timeout_ms);
Como o cliente JavaScript, o setTimeout aceita dois parâmetros. O primeiro parâmetro é a função que precisa ser atrasada e o segundo parâmetro é o tempo de atraso (em milissegundos).
O setTimeout retorna um identificador de tempo limite, que é um objeto interno. Você pode usá -lo como um parâmetro para chamar o ClearTimeout para cancelar o timer. Exceto isso, esse identificador não tem efeito.
Use ClearTimeout para cancelar o plano de execução
Depois que o identificador de tempo limite for obtido, você pode usar o ClearTimeout para cancelar o plano de execução da função, como este:
A cópia do código é a seguinte:
var timeoutTime = 1000; // Um segundo
var timeout = setTimeout (function () {
console.log ("Timed Out!");
}, tempo limite);
ClearTimeout (tempo limite);
Neste exemplo, o cronômetro nunca será acionado e não produzirá as palavras "tempo limite!". Você também pode cancelar o plano de execução a qualquer momento no futuro, como o exemplo a seguir:
A cópia do código é a seguinte:
var timeout = setTimeout (função a () {
console.log ("Timed Out!");
}, 2000);
setTimeout (função b () {
ClearTimeout (tempo limite);
}, 1000);
O código especifica duas funções A e B que são executadas atrasadas. A função A está planejada para ser executada após 2 segundos, e B está planejado para ser executado após 1 segundo, porque a função B é executada primeiro e cancela o plano de execução de A, para que a nunca seja executado.
Desenvolver e cancelar o plano de execução repetitivo da função
O setInterval é semelhante ao Settimeout, mas executará repetidamente uma função em um intervalo de tempo especificado. Você pode usá -lo para acionar periodicamente um programa para concluir algumas outras tarefas que precisam ser repetidas, como limpeza, coleta, log, obter dados, pesquisas, etc.
O código a seguir produzirá um "carrapato" para o console a cada segundo:
A cópia do código é a seguinte:
VAR Período = 1000; // 1 segundo
setInterval (function () {
console.log ("tick");
}, período);
Se você não deseja que seja executado para sempre, pode usar o ClearInterval () para cancelar o timer.
O SetInterval retorna um identificador de plano de execução, que pode ser usado como um parâmetro para limpar o intervalo para cancelar o plano de execução:
A cópia do código é a seguinte:
var interval = setInterval (function () {
console.log ("tick");
}, 1000);
//…
ClearInterval (intervalo);
Use Process.NextTick para atrasar a execução da função na próxima rodada do loop do evento
Às vezes, o programador JavaScript do cliente usa o setTimeout (retorno de chamada, 0) para adiar a tarefa por um curto período de tempo. O segundo parâmetro é 0 milissegundos. Ele diz ao JavaScript para executar essa função de retorno de chamada imediatamente após os eventos pendentes forem processados. Às vezes, essa técnica é usada para atrasar a execução de operações que não precisam ser realizadas imediatamente. Por exemplo, às vezes você precisa começar a reproduzir animações ou fazer outros cálculos após o processamento do evento do usuário.
No nó, assim como o significado literal do "loop de eventos", o loop de eventos é executado em um loop que lida com filas de eventos, e cada rodada no trabalho de loop de eventos é chamada de carrapato.
Você pode ligar para a função de retorno de chamada quando o loop do evento iniciar a próxima rodada (a próxima execução), que é exatamente o princípio do processo.
Ao usar o Process.NextTick (retorno de chamada) em vez de Settimeout (retorno de chamada, 0), sua função de retorno de chamada será executada imediatamente após o processo do evento na fila. É muito mais rápido que a fila de tempo limite do JavaScript (medido pelo tempo da CPU).
Você pode adiar a função até o próximo loop de evento e executá -lo assim:
A cópia do código é a seguinte:
process.NextTick (function () {
my_expensive_computation_function ();
});
Nota: O objeto de processo é um dos poucos objetos globais no nó.
Loop de eventos de bloqueio
O tempo de execução do Node e JavaScript usa um loop de eventos de thread único. Cada loop, o tempo de execução usa a função de retorno de chamada para lidar com o próximo evento na fila. Quando o evento é executado, o loop do evento obtém o resultado da execução e processa o próximo evento, repetindo -o até que a fila do evento esteja vazia. Se um dos retornos de chamada levar muito tempo para ser executado, o loop de eventos não poderá lidar com outros eventos pendentes durante esse período, o que pode tornar o aplicativo ou o serviço muito lento.
Ao processar eventos, se forem usadas funções sensíveis à memória ou sensíveis ao processador, o loop de eventos ficará lento e um grande número de eventos se acumulará, o que não pode ser processado no tempo ou mesmo bloquear a fila.
Veja o seguinte exemplo de bloqueio de loop de eventos:
A cópia do código é a seguinte:
process.nextTick (função nextTick1 () {
var a = 0;
while (true) {
a ++;
}
});
process.nextTick (função nextTick2 () {
console.log ("Next Tick");
});
setTimeout (função timeout () {
console.log ("Timeout");
}, 1000);
Neste exemplo, as funções NextTick2 e Timeout não têm chance de correr, não importa quanto tempo esperam, porque o loop do evento é bloqueado pelo loop infinito na função Nexttick, e não será executada, mesmo que a função de tempo limite esteja programada para ser executada após 1 segundo.
Quando o Settimeout é usado, as funções de retorno de chamada são adicionadas à fila do plano de execução e, nesse caso, elas nem são adicionadas à fila. Embora este seja um exemplo extremo, você pode ver que a execução de uma tarefa sensível ao processador pode bloquear ou desacelerar o loop do evento.
Saia do loop do evento
Usando o Process.NextTick, uma tarefa não crítica pode ser adiada para a próxima rodada do loop do evento (tick) antes da execução, o que pode liberar o loop do evento para que ele possa continuar executando outros eventos pendentes.
Veja o exemplo a seguir. Se você planeja excluir um arquivo temporário, mas não deseja que a função de retorno de chamada do evento de dados aguarde esta operação de IO, você pode atrasá -lo assim:
A cópia do código é a seguinte:
stream.on ("dados", função (dados) {
stream.end ("minha resposta");
process.NextTick (function () {
fs.unlink ("/path/to/file");
});
});
Use o setTimeout em vez de setInterval para garantir a serialidade da execução da função
Suponha que você esteja planejando projetar uma função chamada my_async_function, que pode fazer algumas operações de E/S (como analisar arquivos de log) e pretender fazê -lo executá -lo periodicamente. Você pode implementá -lo com o setInterval como este:
A cópia do código é a seguinte:
intervalo var = 1000;
setInterval (function () {
my_async_function (function () {
console.log ('my_async_function terminado!');
});
}, intervalo); // Nota do tradutor: adicionei o "intervalo" anterior e o autor deveria ter perdido por causa de um erro de digitação
Você deve poder garantir que essas funções não sejam executadas simultaneamente, mas se você usar o SetInterval, não poderá garantir isso. Se a função my_async_function executar um milissegundo por mais tempo que as variáveis de intervalo, elas serão executadas simultaneamente, em vez de em sequência em série.
Nota do tradutor: (A parte em negrito abaixo é adicionada pelo tradutor, não pelo conteúdo do livro original)
Para facilitar a compreensão desta parte do conteúdo, você pode modificar o código do autor para que ele possa realmente executar:
A cópia do código é a seguinte:
intervalo var = 1000;
setInterval (function () {
(function my_async_function () {
setTimeout (function () {
console.log ("1");
}, 5000);
}) ();
},intervalo);
Execute este código e você descobrirá que depois de esperar 5 segundos, "Hello" é a produção a cada 1 segundo. Esperamos que, após a execução atual do my_async_function (tomada 5 segundos), aguarde 1 segundo antes de executar o próximo my_async_function e o intervalo entre cada saída deve ser de 6 segundos. Esse resultado é porque o my_async_function não é executado em série, mas é executado ao mesmo tempo.
Portanto, você precisa de uma maneira de forçar o intervalo entre o final de uma execução de um my_async_function e o início da execução da próxima my_async_function é exatamente o tempo especificado pela variável de intervalo. Você pode fazer isso:
A cópia do código é a seguinte:
intervalo var = 1000; // 1 segundo
(cronograma de função () {// linha 3
setTimeout (function do_it () {
my_async_function (function () {// linha 5
console.log ('Async está pronto!');
agendar();
});
}, intervalo);
} ()); // linha 10
No código anterior, é declarada uma função chamada Cronograma (linha 3) e é chamada imediatamente após a declaração (linha 10). A função de cronograma executará a função DO_IT após 1 segundo (especificado por intervalo). Após 1 segundo, a função my_async_function na linha 5 será chamada. Quando é executado, ele chama sua própria função de retorno de chamada anônima (linha 6). Esta função anônima de retorno de chamada redefinirá o plano de execução do DO_IT novamente e a permitirá ser executada novamente após 1 segundo, para que o código inicie em seriamente e continuamente o executar.
resumo
Você pode usar a função setTimeout () para predefinir o plano de execução da função e cancelá -lo com a função ClearTimeout (). Você também pode usar o setInterval () para executar uma certa função periodicamente repetidamente. Consequentemente, você pode usar o ClearInterval () para cancelar esse plano de execução repetido.
Se o loop do evento for bloqueado usando uma operação sensível ao processador, as funções que foram originalmente planejadas para serem executadas serão adiadas e nunca serão executadas. Portanto, não use operações sensíveis à CPU dentro do loop do evento. Além disso, você pode usar o processo.NextTick () para adiar a execução da função até a próxima rodada do loop do evento.
Ao usar E/S e SetInterval () juntos, você não pode garantir que exista apenas uma chamada pendente a qualquer momento, mas pode usar funções recursivas e funções setTimeout () para evitar esse problema complicado.