1# raf-schd 2 3A `throttle` function that uses [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) to limit the rate at which a function is called. 4 5[![Build Status](https://travis-ci.org/alexreardon/raf-schd.svg?branch=master)](https://travis-ci.org/alexreardon/raf-schd) [![dependencies](https://david-dm.org/alexreardon/raf-schd.svg)](https://david-dm.org/alexreardon/raf-schd) [![npm](https://img.shields.io/npm/v/raf-schd.svg)](https://www.npmjs.com/package/raf-schd) [![SemVer](https://img.shields.io/badge/SemVer-2.0.0-brightgreen.svg)](http://semver.org/spec/v2.0.0.html) 6 7> For background information on rate limiting functions, see [Rate limiting functions from scratch](https://www.youtube.com/watch?v=g_3e_bNU2e0) 8 9```js 10import rafSchd from 'raf-schd'; 11 12const expensiveFn = arg => { 13 //... 14 console.log(arg); 15}; 16 17const schedule = rafSchd(expensiveFn); 18 19schedule('foo'); 20schedule('bar'); 21schedule('baz'); 22 23// animation frame fires 24 25// => 'baz' 26``` 27 28## Why? 29 30`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. 31 32`raf-schd` is an **extremely** useful performance utility. 33 34### Without `raf-schd` 35 36> Optimised scroll listener example taken from [MDN](https://developer.mozilla.org/en-US/docs/Web/Events/scroll) 37 38```js 39var last_known_scroll_position = 0; 40var ticking = false; 41 42function doSomething(scroll_pos) { 43 // do something with the scroll position 44} 45 46window.addEventListener('scroll', function(e) { 47 last_known_scroll_position = window.scrollY; 48 if (!ticking) { 49 window.requestAnimationFrame(function() { 50 doSomething(last_known_scroll_position); 51 ticking = false; 52 }); 53 } 54 ticking = true; 55}); 56``` 57 58### With `raf-schd` 59 60```js 61import rafSchd from 'raf-schd'; 62 63function doSomething(scroll_pos) { 64 // do something with the scroll position 65} 66 67const schedule = rafSchd(doSomething); 68 69window.addEventListener('scroll', function() { 70 schedule(window.scrollY); 71}); 72``` 73 74At the top level `raf-schd` accepts any function a returns a new `ResultFn` (a function that wraps your original function). 75 76The `ResultFn` will execute your function with the **latest arguments** provided to it on the next animation frame. 77 78### Throttled with latest argument 79 80```js 81import rafSchd from 'raf-schd'; 82 83const doSomething = () => {...}; 84 85const schedule = rafSchd(doSomething); 86 87schedule(1, 2); 88schedule(3, 4); 89schedule(5, 6); 90 91// animation frame fires 92 93// do something called with => '5, 6' 94``` 95 96### Cancelling a frame with `.cancel` 97 98`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. 99 100```js 101const schedule = rafSchd(doSomething); 102 103schedule('foo'); 104 105schedule.cancel(); 106 107// now doSomething will not be executed in the next animation frame 108``` 109 110## Types 111 112### `rafSchedule` 113 114```js 115type rafSchedule = (fn: Function) => ResultFn; 116 117// Adding a .cancel property to the WrapperFn 118 119type WrapperFn = (...arg: mixed[]) => void; 120type CancelFn = {| 121 cancel: () => void, 122|}; 123type ResultFn = WrapperFn & CancelFn; 124``` 125 126## Testing your code 127 128If you want to really ensure that your code is working how you intend it to - use [`raf-stub`](https://github.com/alexreardon/raf-stub) to test your animation frame logic. 129 130## Installation 131 132```bash 133# yarn 134yarn add raf-schd 135 136# npm 137npm install raf-schd --save 138``` 139 140## Module usage 141 142### ES6 module 143 144```js 145import rafSchd from 'raf-schd'; 146``` 147 148### CommonJS 149 150If you are in a CommonJS environment (eg [Node](https://nodejs.org)), then **you will need add `.default` to your import**: 151 152```js 153const rafSchd = require('raf-schd').default; 154``` 155