Melhor maneira de obter tempo em milissegundos em javascript?

141

Existe uma alternativa no JavaScript de obter tempo em milissegundos usando o objeto de data ou pelo menos uma maneira de reutilizá-lo, sem ter que instanciar um novo objeto toda vez que eu precisar obter esse valor? Estou perguntando isso porque estou tentando criar um mecanismo de jogo simples em JavaScript e, ao calcular o "tempo de quadro delta", tenho que criar um novo objeto Date a cada quadro. Embora não esteja muito preocupado com as implicações de desempenho disso, estou tendo alguns problemas com a confiabilidade do tempo exato retornado por esse objeto.

Eu recebo alguns "pulos" estranhos na animação, a cada segundo ou mais, e não tenho certeza se isso está relacionado à Coleta de Lixo do JavaScript ou a uma limitação do objeto Date ao atualizar tão rápido. Se eu definir o valor delta como uma constante, a animação será perfeitamente suave, por isso tenho certeza de que esse "salto" está relacionado à maneira como ganho o tempo.

O único código relevante que posso fornecer é a maneira como calculo o tempo delta:

prevTime = curTime;
curTime = (new Date()).getTime();
deltaTime = curTime - prevTime;

Ao calcular movimento / animação, multiplico um valor constante pelo tempo delta.

Se não há como evitar o tempo em milissegundos usando o objeto Date, uma função que incrementa uma variável (sendo o tempo decorrido em milissegundos desde o início do jogo) e é chamada usando a função SetTimer a uma taxa de uma vez a cada milissegundo ser uma alternativa eficiente e confiável?

Edit: Eu testei agora meu código em diferentes navegadores e parece que esse "salto" é realmente aparente apenas no Chrome, não no Firefox. Mas ainda seria bom se houvesse um método que funcionasse nos dois navegadores.

Colin Dumitru
fonte
5
Um objeto por quadro não
CodesInChaos
2
Sobre a animação pulando a cada segundo, isso poderia ter algo a ver com o fato de Date.getMillisecondsretornar apenas os milissegundos no segundo atual, ou seja, de 0 a 999? Você não está usando esta função no seu exemplo, mas talvez ela esteja sendo usada em outro lugar ou em uma ramificação diferente?
Dan Ross
2
O salto está relacionado a alguns problemas estranhos de resolução de milissegundos? Nos documentos da Mozilla : "Ao usar now () para criar registros de data e hora ou IDs exclusivos, lembre-se de que a resolução pode ser de 15 milissegundos no Windows". Isso poderia estar relacionado aos soluços?
Zashu 26/03
1
@ zashu isso foi há muito tempo, então não me lembro de detalhes específicos para este exemplo. Mas para aplicativos mais recentes, ao usar Date.now (), não vejo mais pulos.
Colin Dumitru 26/03

Respostas:

173

Tente Date.now () .

O salto provavelmente ocorre devido à coleta de lixo. Normalmente, a coleta de lixo pode ser evitada reutilizando as variáveis ​​o máximo possível, mas não posso dizer especificamente quais métodos você pode usar para reduzir as pausas na coleta de lixo.

Joeri Sebrechts
fonte
1
Eu tentei usar Date.now (), mas ainda tenho os mesmos saltos. Portanto, agora tenho certeza de que não há problema com a coleta de lixo, mas uma limitação ao obter valores exatos com o objeto Date. Como eu disse, substituir o tempo delta por um valor constante resulta em animações / transições suaves; portanto, a única coleta de lixo que pode estar acontecendo é com "new Date" ou "Date.now ()" (se essa função instancia seus próprios objetos que Eu não sei sobre).
Colin Dumitru
22
Apenas um heads-up: Isso não funciona no IE8 e abaixo
Nick
1
Eu faço: / Tudo o que eu quero é a data em ms. Parece tão complicado para algo tão necessário.
Damien Golding
5
@Prozi +1 .. IE realmente é uma porcaria, quando Im web programação Eu cuidado realmente não sobre IE, apenas Chrome e Firefox ..........
TechLife
3
@TechLife Você também deve pensar nos navegadores Android, Safari e Opera, mas eu concordo que o IE é um monte de lixo. Quero dizer, é tão ruim que MS desistiram e estão a implementar um novo navegador em W10
Dendromaniac
49

Eu sei que esse é um tópico bastante antigo, mas para manter as coisas atualizadas e mais relevantes, você pode usar a performance.now()funcionalidade mais precisa para obter um melhor tempo de granulação em javascript.

window.performance = window.performance || {};
performance.now = (function() {
    return performance.now       ||
        performance.mozNow    ||
        performance.msNow     ||
        performance.oNow      ||
        performance.webkitNow ||            
        Date.now  /*none found - fallback to browser default */
})();
Chris GW Green
fonte
2
A última alternativa deve ser apenas Date.nowem vez de uma expressão de função anônima
Bergi
1
Também não funciona em navegadores antigos estúpidos, infelizmente. Felizmente, convenci meus clientes a me pagar pelo tempo que perdi apoiando o IE7 e o IE8.
Michael Scheper
2
|| function () {return new Date (). getTime ()}
mmm
2
Vale a pena notar que performance.now()dá tempo monotônico, ao contrário do tempo Date. Isso significa que todas as chamadas subseqüentes são garantidas para retornar um valor não inferior ao anterior.
usuário
48

Tanto quanto sei, você só pode ter tempo com o Date .

Date.now é a solução, mas não está disponível em todos os lugares: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/now .

var currentTime = +new Date();

Isso fornece o tempo atual em milissegundos.

Para seus saltos . Se você calcular as interpolações corretamente de acordo com o tempo do quadro delta e não tiver algum erro de número de arredondamento , aposto no coletor de lixo (GC).

Se houver muitos objetos temporários criados no seu loop, a coleta de lixo precisará bloquear o encadeamento para fazer alguma limpeza e reorganização da memória.

Com o Chrome, você pode ver quanto tempo o GC está gastando no painel Linha do tempo .

Edição: Desde a minha resposta, Date.now()deve ser considerada como a melhor opção, pois é suportada em todos os lugares e no IE> = 9.

ngryman
fonte
4
Em que função o +serviço serve +new?
Andrew Scagnelli
33
O +simplesmente lançar Datea Number, dando um timestamp unix padrão em milissegundos. Você pode explicitamente obter esse valor chamando(new Date()).getTime()
ngryman
9
@mikenelson: Não é terrível para mim, isso é óbvio quando você sabe como funciona a coerção Date.now().
Ncedman
1
Eu prefiro apenas +que .getTime()... É mais simples e eu não preciso memorizar os nomes de funções
2
@TravisJ Awesome shortcut? Para recuperar um valor numérico que já está dentro do computador, você cria um objeto, chame um operador que testa um int e aciona uma conversão que chama uma função (valueOf) que chama o método de conversão de classe que chama uma função (getTime) que finalmente recupera o valor. Em seguida, o objeto é abandonado ao seu destino e, após 1000 iterações do loop, você tem 1000 objetos Date excluídos que requerem coleta de lixo pendurada lá, que de repente se juntam e, enquanto o computador fica lento, você se pergunta o que está acontecendo. :) Impressionante!
FrancescoMM
7

Se você tiver um objeto de data como

var date = new Date('2017/12/03');

existe um método embutido no javascript para obter a data no formato de milissegundos, que é valueOf ()

date.valueOf(); //1512239400000 in milliseconds format
dilip kumar
fonte
2

Essa é uma pergunta muito antiga - mas ainda para referência, se outras pessoas estiverem olhando para ela - requestAnimationFrame()é a maneira certa de lidar com a animação nos navegadores modernos:

ATUALIZAÇÃO: O link do mozilla mostra como fazer isso - não estava com vontade de repetir o texto por trás do link;)

LarsKnudsen
fonte
4
Bem-vindo ao Stack Overflow ! Você pode incluir uma breve explicação do que requestAnimationFrameisso impede esse "salto", conforme descrito na pergunta. Obrigado!
Qantas 94 Heavy
2
Mesmo com requestAnimationFrame, não devemos assumir que a taxa de quadros seja a mesma em todas as plataformas, portanto, ainda precisamos verificar a hora atual.
21714 Tom Boutell