Pergunta

Eu pensei que eu iria tentar ser inteligente e criar uma função de Espera de minha própria (eu sei que existem outras maneiras de fazer isso).Então, eu escrevi:

var interval_id;
var countdowntimer = 0;

function Wait(wait_interval) {
  countdowntimer = wait_interval;

  interval_id = setInterval(function() {
    --countdowntimer <=0 ? clearInterval(interval_id) : null;
  }, 1000);

  do {} while (countdowntimer >= 0);
}

// Wait a bit: 5 secs
Wait(5);

Tudo isso funciona, exceto para o loop infinito.Após a inspeção, se eu tomar o tempo de saída de loop, a função anônima é introduzido 5 vezes, conforme o esperado.Então, claramente, a variável global countdowntimer é diminuído.

No entanto, se eu verificar o valor de countdowntimer, no loop While, ele nunca desce.Isto apesar do fato de que a função anônima está sendo chamado, enquanto no loop While!

Claramente, de alguma forma, há dois valores de countdowntimer flutuando, mas por quê?

EDITAR

Ok, então, eu entendo (agora) que o Javascript é único thread.- E que espécie de - responde a minha pergunta.Mas, a que ponto o processamento de uma única thread, a assim chamada chamada assíncrona usando setInterval realmente acontecer?É apenas entre chamadas de função?Certamente não, que sobre as funções que levam um longo tempo para executar?

Foi útil?

Solução

Não há duas cópias da variável por aí. JavaScript em navegadores da web é Único rosqueado (a menos que você use o Novos trabalhadores da web). Portanto, a função anônima nunca tem a chance de correr, porque Wait está amarrando o intérprete.

Você não pode usar funções de espera ocupada no JavaScript baseado em navegador; Nada mais acontecerá (e eles são uma má idéia na maioria dos outros ambientes, mesmo onde são possíveis). Você precisa usar retornos de chamada. Aqui está uma reformulação minimalista disso:

var interval_id;
var countdowntimer = 0;

function Wait(wait_interval, callback) {
    countdowntimer = wait_interval;

    interval_id = setInterval(function() {
        if (--countdowntimer <=0) {
            clearInterval(interval_id);
            interval_id = 0;
            callback();
        }
    }, 1000);
}

// Wait a bit: 5 secs
Wait(5, function() {
    alert("Done waiting");
});

// Any code here happens immediately, it doesn't wait for the callback

Editar Respondendo ao seu acompanhamento:

Mas, em que ponto no processamento deste único thread, a chamada chamada assíncrona usando o setInterval realmente acontece? É apenas entre chamadas de função? Certamente não, e as funções que levam muito tempo para executar?

Praticamente, sim-e é importante que as funções não sejam de longa duração. (Tecnicamente, nem sequer é entre chamadas de função, pois se você tiver uma função que chama outras três funções, o intérprete não pode fazer mais nada enquanto essa função (externa) está em execução.) O intérprete mantém essencialmente uma fila de funções necessárias executar. O início começa executando qualquer código global (como uma grande chamada de função). Então, quando as coisas acontecem (eventos de entrada do usuário, a hora de ligar para um retorno de chamada agendado via setTimeout é alcançado, etc.), o intérprete empurra as chamadas que precisa fazer na fila. Ele sempre processa a chamada na frente da fila, e então as coisas podem se acumular (como o seu setInterval chamadas, embora setInterval é um pedaço Especial - não vai fazer fila um retorno de chamada subsequente se um anterior ainda estiver na fila esperando para ser processado). Portanto, pense em termos de quando seu código obtém controle e quando libera controle (por exemplo, retornando). O intérprete pode Faça outras coisas depois de liberar o controle e antes de devolvê -lo novamente. E novamente, em alguns navegadores (ou seja, por exemplo), esse mesmo tópico também é usado para pintar a interface do usuário e tal, para que as inserções de DOM (por exemplo) não apareçam até que você solte o controle de volta ao navegador para que possa ficar em fazer sua pintura.

Quando JavaScript nos navegadores da Web, você realmente precisa adotar uma abordagem orientada a eventos para projetar e codificar suas soluções. O exemplo clássico está solicitando o usuário para obter informações. Em um mundo não orientado a eventos, você pode fazer isso:

// Non-functional non-event-driven pseudo-example
askTheQuestion();
answer = readTheAnswer();      // Script pauses here
doSomethingWithAnswer(answer); // This doesn't happen until we have an answer
doSomethingElse();

Isso não funciona em um mundo orientado a eventos. Em vez disso, você faz isso:

askTheQuestion();
setCallbackForQuestionAnsweredEvent(doSomethingWithAnswer);
// If we had code here, it would happen *immediately*,
// it wouldn't wait for the answer

Então, por exemplo, askTheQuestion Pode sobrepor uma div na página com campos solicitando o usuário para obter várias informações com um botão "OK" para que eles cliquem quando terminarem. setCallbackForQuestionAnswered estaria realmente conectado ao click Evento no botão "OK". doSomethingWithAnswer coletaria as informações dos campos, removeria ou ocultaria a div e fazer algo com as informações.

Outras dicas

A maioria Javascript implementação single threaded, e , então, quando ele está executando a while loop, ele não deixa nada execução, de modo a interval nunca é executado enquanto o while está em execução, assim, fazer um loop infinito.

Existem muitas tentativas de criar um suspensão/espera/pausa função no javascript, mas uma vez que a maioria das implementações são de thread único, ele simplesmente não deixar de fazer qualquer outra coisa durante o sono(!).

A forma alternativa de fazer um atraso é escrever tempos de espera.Eles podem adiar uma execução de um bloco de código, mas você tem que quebrá-lo em muitas funções.Você sempre pode funções inline então ele se torna mais fácil de seguir (e para compartilhar variáveis dentro de um mesmo contexto de execução).

Existem também algumas bibliotecas que adiciona alguns syntatic suggar javascript para torná-lo mais legível.

EDITAR: Há um excelente post no blog John Resig - se sobre Como o javascript temporizadores funcionam.Ele praticamente explica isso em detalhes.Espero que ajude.

Na verdade, é praticamente garantido que a função de intervalo nunca será executada enquanto o loop faz, pois o JavaScript é um thread único.

Há uma razão pela qual ninguém fez Wait antes (e muitos já tentaram); Simplesmente não pode ser feito.

Você precisará recorrer à sua função em bits e agendá -los usando o setTimeout ou o SetInterval.

//first part
...
setTimeout(function(){
    //next part
}, 5000/*ms*/);

Dependendo das suas necessidades, isso pode (deve) ser implementado como uma máquina de estado.

Em vez de usar uma variável Global CountdownTimer, por que não alterar o atributo milissegundo no setInterval? Algo como:

var waitId;

function Wait(waitSeconds)
{
    waitId= setInterval(function(){clearInterval(waitId);}, waitSeconds * 1000);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top