代码如何检测动画帧内是否有 运行?

How can code detect if running inside an animation frame?

如果将某个函数传递给 requestAnimationFrame(),该函数如何检测到它是在动画帧内调用的?

f.e.

function someFunction() {
  if (/* What goes here? */) {
    console.log('Inside animation frame.')
  }
  else {
    console.log('Not inside animation frame.')
  }
}

// The following lines should not be modified for the answer.
someFunction() // logs "Not inside animation frame."
requestAnimationFrame(someFunction) // eventually logs "Inside animation frame."

最后两行不要修改。我很想知道我是否可以在不需要用户记住以两种不同方式使用该功能的情况下检测到这种情况。最终用户应该像平常一样使用函数,而不知道我的函数检测到用例。

您可以 bind 您传递给 requestAnimationFrame 的函数。

function someFunction(isInsideAnimationFrame, domHighResTimestamp) {
  if (isInsideAnimationFrame) {
    console.log('Inside animation frame.')
  }
  else {
    console.log('Not inside animation frame.')
  }
}

someFunction() // logs "Not inside animation frame."

requestAnimationFrame(someFunction.bind(null, true)) // eventually logs "Inside animation frame."

有关其工作原理的详细信息,请参阅 Function.prototype.bind

更新

查看 window.requestAnimationFrame 的文档,回调即 someFunction 将使用 DOMHighResTimeStamp 调用,即 .

someFunction 可以用

检测到这个
function someFunction(domHighResTimestamp) {
  if (domHighResTimestamp) {
    console.log('Inside animation frame.')
  }
  else {
    console.log('Not inside animation frame.')
  }
}

不幸的是,不能保证使用 someFunction 的人不会调用它来传递值。

目前无法在 Javascript 中获取调用代码的上下文,因此除非您更改 requestAnimationFrame(),否则您无法做您想做的事,但幸运的是您可以做到。试试这个...

// save a reference to the existing method and then override it...
window._requestAnimationFrame = window.requestAnimationFrame;
window.requestAnimationFrame = function(callback) {
 return window._requestAnimationFrame(function() {
  callback(true);
 });
}

function someFunction() {
 if (arguments.length && arguments[0]) {
  console.log('Inside animation frame.')
 }
 else {
  console.log('Not inside animation frame.')
 }
}

someFunction();
requestAnimationFrame(someFunction);

把我自己的答案放在这里供参考(感谢@phuzi、@Archer 和@spender):

// save a reference to the existing method and then override it...
window.requestAnimationFrame = function (raf) { return function(callback) {
  return raf(function(time) {
    callback(time, true);
  });
}}(window.requestAnimationFrame.bind(window))

function someFunction(time, inFrame = false) {
  if (inFrame) {
    console.log('Inside animation frame.')
  }
  else {
    console.log('Not inside animation frame.')
  }
}

someFunction(); // logs "Not inside animation frame."
someFunction(63245); // still logs "Not inside animation frame."
requestAnimationFrame(someFunction); // eventually logs "Inside animation frame."