1 | # `@shopify/function-enhancers`
|
2 |
|
3 | [![Build Status](https://travis-ci.org/Shopify/quilt.svg?branch=master)](https://travis-ci.org/Shopify/quilt)
|
4 | [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE.md) [![npm version](https://badge.fury.io/js/%40shopify%2Ffunction-enhancers.svg)](https://badge.fury.io/js/%40shopify%2Ffunction-enhancers.svg) [![npm bundle size (minified + gzip)](https://img.shields.io/bundlephobia/minzip/@shopify/function-enhancers.svg)](https://img.shields.io/bundlephobia/minzip/@shopify/function-enhancers.svg)
|
5 |
|
6 | A set of helpers to enhance functions.
|
7 |
|
8 | ## Installation
|
9 |
|
10 | ```bash
|
11 | $ yarn add @shopify/function-enhancers
|
12 | ```
|
13 |
|
14 | ## Usage
|
15 |
|
16 | ### `memoize`
|
17 |
|
18 | The memoize decorator creates a function that memoizes the results of the function it is decorating.
|
19 | The cache key for storing the results is based on the first argument provided to the memoized function.
|
20 | If the memoization key cannot be inferred from the first argument alone, a `resolver` should be passed in to ensure a unique key. (ex: the unique key is in the second argument, or the unique key is a combination of a few arguments)
|
21 |
|
22 | Know that memoization will be skipped on server process and the cached results have a maximum limit of 50 entries on a first in first out basis.
|
23 |
|
24 | #### Memoizing a simple function
|
25 |
|
26 | ```ts
|
27 | import {memoize} from '@shopify/function-enhancers';
|
28 |
|
29 | const addOne = (number: number) => {
|
30 | return number + 1;
|
31 | };
|
32 |
|
33 | const addOneMemoized = memoize(addOne);
|
34 |
|
35 | addOneMemoized(1); // -> 2, addOne is executed
|
36 | addOneMemoized(1); // -> 2, result is from cache
|
37 | ```
|
38 |
|
39 | #### Memoizing a function with object as argument
|
40 |
|
41 | When memoizing a function with object as first argument, make sure the object is immutable.
|
42 |
|
43 | ```ts
|
44 | import {memoize} from '@shopify/function-enhancers';
|
45 |
|
46 | const getValues = (someObject: {one: string; two: string}) => {
|
47 | return;
|
48 | };
|
49 |
|
50 | const getValuesMemoized = memoize(getValues);
|
51 |
|
52 | const testObject1 = {one: 1, two: 2};
|
53 | getValuesMemoized(testObject1); // -> [1, 2], getValues is executed
|
54 | getValuesMemoized(testObject1); // -> [1, 2], result is from cache
|
55 |
|
56 | testObject1.two = 3;
|
57 | getValuesMemoized(testObject1); // -> [1, 2], result is from cache, BAD
|
58 | ```
|
59 |
|
60 | #### Memoizing a function while providing a resolver
|
61 |
|
62 | The resolver takes in the same arguments as the function it is enhancing.
|
63 | Be sure that the resolver returns a unique identifer.
|
64 |
|
65 | ```ts
|
66 | import {memoize} from '@shopify/function-enhancers';
|
67 |
|
68 | const getByCommand = (command: string, value: string) => {
|
69 | // implementation for getByCommand
|
70 | };
|
71 |
|
72 | const getByCommandMemoized = memoize(
|
73 | getByCommand,
|
74 | (command: string, value: string) => `${command}${value}`,
|
75 | );
|
76 |
|
77 | getByCommandMemoized('command name 1', 'command value 1'); // runCommand is executed
|
78 | getByCommandMemoized('command name 1', 'command value 2'); // runCommand is executed
|
79 | ```
|
80 |
|
81 | Next let's fix the example from [above](#memoizing-a-function-with-object-as-argument) so the results will always be correct.
|
82 |
|
83 | ```ts
|
84 | import {memoize} from '@shopify/function-enhancers';
|
85 |
|
86 | const getByCommand = (command: string, value: string) => {
|
87 | // implementation for getByCommand
|
88 | };
|
89 |
|
90 | const getByCommandMemoized = memoize(
|
91 | getByCommand,
|
92 | (command: string, value: string) => `${command}${value}`,
|
93 | );
|
94 |
|
95 | const testObject1 = {id: 1, value: 2};
|
96 | getByCommandMemoized(testObject1); // -> [1, 2], getValues is executed
|
97 | getByCommandMemoized(testObject1); // -> [1, 2], result is from cache
|
98 |
|
99 | testObject1.value = 3;
|
100 | getByCommandMemoized(testObject1); // -> [1, 3], getValues is executed
|
101 | ```
|