RequestAnimationFrame () allinea davvero con gli aggiornamenti del monitor?

1

Prendi questo codice:

requestAnimationFrame(function (timestamp) {
  console.log('one', timestamp);
});

requestAnimationFrame(function (timestamp) {
  console.log('two', timestamp);
});

// logs:
// "one", 184.6999999834225
// "two", 184.6999999834225

Il timestamp è di millisecondi poiché la pagina è stata caricata. Nota queste due chiamate rAF restituiscono ID diversi che puoi cancellare singolarmente.

Ora facciamo in modo che la prima callback faccia qualcosa di molto costoso:

requestAnimationFrame(function (timestamp) {
  console.log('one', timestamp);

  // block for 1 second
  const endAt = Date.now() + 1000;
  while (true) {
    if (Date.now() >= endAt) break;
  }
});

requestAnimationFrame(function (timestamp) {
  console.log('two', timestamp);
});


// LOGS:
//   "one", 189.32800000533462
//   "two", 189.32800000533462  (this appears one second later)

Sono confuso: il secondo viene eseguito un intero secondo dopo, ma ottiene lo stesso timestamp. Perché non può ottenere un nuovo timestamp, uno corrispondente a quello che il frame di aggiornamento del monitor corrente è ora nel momento in cui viene chiamato?

Se rAF decide in anticipo che il callback deve essere eseguito nello stesso frame di un altro callback, indipendentemente da quanto possa richiedere l'altra callback, il 'frame' sembra un concetto privo di significato che non corrisponde a un callback aggiornamento singolo monitor - quindi qual è il punto?

Sono sicuro che c'è una buona ragione per cui è implementata in questo modo, voglio solo capirlo.

    
posta callum 22.07.2015 - 14:40
fonte

1 risposta

1

Queste due funzioni sono pianificate per essere eseguite nello stesso momento, ma in realtà non verranno mai eseguite contemporaneamente in un ambiente a thread singolo. Funzioneranno in sequenza.

Ma mentre stanno eseguendo il rendering del browser è bloccato e qualsiasi effetto che fanno avverrà nello stesso momento in cui entrambi finiscono.

È logico che il timestamp sia lo stesso perché qualsiasi effetto visibile di tali funzioni avverrà nello stesso momento - quindi ad es. se stai animando due auto con la stessa velocità, ti aspetteresti che si muovano sempre in sincronia, indipendentemente dal tempo necessario per calcolare la posizione di ognuna di esse.

Vedi questo DEMO su jsbin:

// noprotect
var p1 = document.getElementById('p1');
var p2 = document.getElementById('p2');

requestAnimationFrame(function (timestamp) {
  console.log('one', timestamp);

  // block for 3 second
  var endAt = Date.now() + 3000;
  while (true) {
    if (Date.now() >= endAt) break;
  }
  p1.innerHTML = timestamp;
});

requestAnimationFrame(function (timestamp) {
  console.log('two', timestamp);

  // block for 3 second
  var endAt = Date.now() + 3000;
  while (true) {
    if (Date.now() >= endAt) break;
  }
  p2.innerHTML = timestamp;
});

Ho modificato il tuo esempio per impiegare più tempo (3 secondi) affinché gli effetti siano più visibili e per manipolare il DOM. Sono state apportate altre modifiche per evitare gli avvisi jsbin.

Come puoi vedere entrambe le manipolazioni del DOM diventano visibili esattamente nello stesso momento, quindi sarebbe strano se i timestamp fossero diversi.

Questi timestamp sono lì per essere usati per calcolare le posizioni degli oggetti animati o altri valori dipendenti dal tempo. E se due funzioni sono state programmate contemporaneamente, avranno lo stesso timestamp.

    
risposta data 23.07.2015 - 22:07
fonte

Leggi altre domande sui tag