2016-11-03 6 views
3

Если какая-либо функция передается в 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." 

Последние две строки не следует изменять. Мне интересно узнать, могу ли я обнаружить ситуацию, не требуя, чтобы пользователь не забывал использовать эту функцию двумя разными способами. Конечный пользователь должен просто использовать функцию, как обычно, не зная, что моя функция определяет прецедент.

+1

Вы всегда можете передать что-то из сайта вызова: 'requestAnimationFrame (function() {someFunction (true)})' vs 'someFunction (false)'. – spender

+0

Это правда, но если моя функция предоставляется другим людям для использования, нет никакой гарантии, что они это сделают. Или другие люди могут даже не знать, что они называют эту функцию опосредованно. – trusktr

+0

Параметры ES6 по умолчанию могут помочь с этим: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters – spender

ответ

0

Вы можете отправить 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 не называть его передачи значения.

+0

Привет phuzi, как и комментарии автора, пользователь моей функции может или не может этого сделать. Если бы это был только мой собственный код, тогда да, это было бы легко. Я уточню вопрос. – trusktr

+0

Обновлен мой вопрос: последние две строки в этом примере не должны быть изменены. – trusktr

+0

Обновлен мой ответ альтернативой. Я не уверен, что есть 100% -ный надежный способ обнаружить то, что вы хотите. – phuzi

2

В настоящее время невозможно получить контекст вызывающего кода в Javascript, поэтому вы не можете делать то, что хотите, если не измените requestAnimationFrame(), но, к счастью, вы можете это сделать. Попробуйте это ...

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

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

 
someFunction(); 
 
requestAnimationFrame(someFunction);

+0

Скорее всего, OP будет нуждаться в полиполке в любом случае, так что это было бы просто добавить. – user5542121

+0

Бит избытка - обратный вызов будет вызываться с помощью одного аргумента, 'DOMHighResTimeStamp', если он вызывается в контексте кадра анимации. – phuzi

+0

Хорошая идея. Но забавная вещь в вашем конкретном примере она все еще работает без патча обезьяны. – trusktr

2

Положив свой ответ здесь для справки (спасибо @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."