1

Take this code:

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

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

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

The timestamp is milliseconds since the page loaded. Note these two rAF calls return different IDs which you can cancel individually.

Now let's make the first callback do something very expensive:

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)

I'm confused: the second one runs a whole second later, but gets the same timestamp. Why can't it get a new timestamp, one corresponding with whatever the current monitor refresh frame is now at the time it's being called?

If rAF decides ahead of time that your callback must be run in the same frame as another callback, regardless of how long that other callback might take, then the 'frame' seems like a meaningless concept that doesn't correspond with a single monitor refresh - so what's the point?

I'm sure there's a good reason why it's implemented this way, I just want to understand it.

1

Those two functions are scheduled to be run at the same time, but will actually never run at the same time in a single-threaded environment. They will run in sequence.

But while they are running the browser rendering is blocked and any effect that they do will happen at the same time when they both finish.

It makes sense for the timestamp to be the same because any visible effects of those functions will happen at the same time - so e.g. if you are animating two cars with the same speed then you would expect them to be always moving in sync, no matter how long it takes to calculate the position of any of them.

See this DEMO on 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;
});

I changed your example to take longer (3 sec) for the effects to be more visible and to manipulate the DOM. Other changes were made to avoid jsbin warnings.

As you can see both of the DOM manipulations get visible at exactly the same time, so it would be strange if the timestamps were different.

Those timestamps are there to be used to calculate the positions of animated objects or other time dependent values. And if two functions were scheduled at the same time then they will have the same timestamp.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.