What is raf-schd?
The raf-schd package is a small utility that creates a throttled function that only invokes the provided function at most once per animation frame. It's useful for optimizing performance by reducing the number of times a function is called during rapid events such as scrolling, resizing, or animations.
What are raf-schd's main functionalities?
Throttling function calls
This code sample demonstrates how to create a throttled version of an expensive function that is called at most once per animation frame. This is useful for attaching to events that fire rapidly, such as 'resize' or 'scroll' events.
import schedule from 'raf-schd';
const expensiveFunction = () => {
// Expensive operation
};
const throttledFunction = schedule(expensiveFunction);
window.addEventListener('resize', throttledFunction);
window.addEventListener('scroll', throttledFunction);
Other packages similar to raf-schd
throttle-debounce
The throttle-debounce package provides throttle and debounce functions that can be used to rate-limit functions. It is similar to raf-schd in that it helps in optimizing function execution frequency, but it does not specifically tie the throttling to requestAnimationFrame.
lodash.throttle
lodash.throttle is a function from the popular Lodash library that throttles a function call. It is similar to raf-schd but offers more customization options, such as leading and trailing invocation control. Unlike raf-schd, it does not use requestAnimationFrame and allows setting a custom delay.
frame-throttle
frame-throttle is a package that provides a similar functionality to raf-schd by throttling function calls to the next animation frame. It is a direct alternative to raf-schd, with a similar API and use case.
raf-schd
A throttle
function that uses requestAnimationFrame
to limit the rate at which a function is called.
For background information on rate limiting functions, see Rate limiting functions from scratch
import rafSchd from 'raf-schd';
const expensiveFn = arg => {
console.log(arg);
};
const schedule = rafSchd(expensiveFn);
schedule('foo');
schedule('bar');
schedule('baz');
Why?
raf-schd
supports the use case where you want to limit the rate at which your functions are called based on requestAnimationFrame
. Unlike a standard throttle
function, raf-schd
uses requestAnimationFrame
to rate limit, rather than waiting a fixed amount of time. Using requestAnimationFrame
for throttling is powerful because the browser will automatically reduce the amount of frames provided based on the available resources. So if the browser only provides 30fps then your throttled function will only be called 30 times.
raf-schd
is an extremely useful performance utility.
Without raf-schd
Optimised scroll listener example taken from MDN
var last_known_scroll_position = 0;
var ticking = false;
function doSomething(scroll_pos) {
}
window.addEventListener('scroll', function(e) {
last_known_scroll_position = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function() {
doSomething(last_known_scroll_position);
ticking = false;
});
}
ticking = true;
});
With raf-schd
import rafSchd from 'raf-schd';
function doSomething(scroll_pos) {
}
const schedule = rafSchd(doSomething);
window.addEventListener('scroll', function() {
schedule(window.scrollY);
});
At the top level raf-schd
accepts any function a returns a new ResultFn
(a function that wraps your original function).
The ResultFn
will execute your function with the latest arguments provided to it on the next animation frame.
Throttled with latest argument
import rafSchd from 'raf-schd';
const doSomething = () => {...};
const schedule = rafSchd(doSomething);
schedule(1, 2);
schedule(3, 4);
schedule(5, 6);
Cancelling a frame with .cancel
raf-schd
adds a .cancel
property to the ResultFn
so that it can be easily cancelled. The frame will only be cancelled if it has not yet executed.
const schedule = rafSchd(doSomething);
schedule('foo');
schedule.cancel();
Types
rafSchedule
type rafSchedule = (fn: Function) => ResultFn;
type WrapperFn = (...arg: mixed[]) => void;
type CancelFn = {|
cancel: () => void,
|};
type ResultFn = WrapperFn & CancelFn;
Testing your code
If you want to really ensure that your code is working how you intend it to - use raf-stub
to test your animation frame logic.
Installation
yarn add raf-schd
npm install raf-schd --save
Module usage
ES6 module
import rafSchd from 'raf-schd';
CommonJS
If you are in a CommonJS environment (eg Node), then you will need add .default
to your import:
const rafSchd = require('raf-schd').default;