npm package: @forivall/promise-memoize
Description: Memoize promise-returning functions. Includes cache expire and prefetch.
Latest version: 1.0.1

# promise-memoize

[![Build Status](https://img.shields.io/travis/forivall/promise-memoize/master.svg?style=flat)](https://travis-ci.org/forivall/promise-memoize)
[![NPM version](https://img.shields.io/npm/v/promise-memoize.svg?style=flat)](https://www.npmjs.org/package/promise-memoize)
[![Coverage Status](https://coveralls.io/repos/github/forivall/promise-memoize/badge.svg?branch=master)](https://coveralls.io/github/forivall/promise-memoize?branch=master)

> Memoize promise-returning functions. Includes cache expire and prefetch.

- When data expire mode enabled, new values are fetched in advance. Cache
  will be always valid, without "gaps".
  - Prefetch happens only for items in use. Inactive ones will be GC-ed as usual.
- Errors are not cached
  - You still can enable cache with separate expire time for errors, to avoid
    specific peak loads. For example, set 120s for good result and 1s on fail.


## Install

```bash
npm install @forivall/promise-memoize --save
```


## Usage example

```js
// Pseudo code
let db = require('mongoose').createConnection('mongodb://localhost/forum');

function lastPosts(limit) {
  return db.model('Post').find().limit(limit).orderBy('-_id').lean(true).exec(); // <- Promise
}

let cachedLastPosts = require('@forivall/promise-memoize')(lastPosts, { maxAge: 60000 });

// Later...
cachedLastPosts(10).then(posts => console.log(posts));
```

## API

### promiseMemoize(fn [, options]) -> memoizedFn

Memoize function `fn`.

 - **fn(params...)** — function, returning a promise (or any "thenable").
   It can have any number of arguments, but arguments should be uniquely
   castable to strings (see below).
 - **options** — options for memoization (optional)
   - **maxAge** — an amount of milliseconds it should cache resolved
     values for (default: `Infinity`, i.e. cache forever).
   - **maxErrorAge** — an amount of milliseconds it should cache
     rejected values for (default: `0`, i.e. don't cache).
   - **resolve** — serialiser to build unique key from `fn` arguments.
     (default: `simple`). Possible values:
     - `simple` (string) — convert each param to string & join those.
     - `json` (string) — JSON.stringify each param & join results.
     - function(Array) — custom function, with `fn` params as array on input
     - `[ String, Boolean, 'json', function ]` — array with custom functions,
       specific for each `fn` param position (text shortcuts as above are allowed).

Return value is a function with the same signature as *fn*.

**Note. How prefetch works.**

If `maxAge` used and request to cached data happens after `0.7 * maxAge` time, then:

- cached data returned
- `fn` call is executed in parallel
- cached data will be substituted with new one on success, timeouts will be extended.

So your application will not have to wait for data fetch after cache expire.


### memoizedFn(params...) -> promise

Returns result as cached promise (errors are not cached by default). If `maxAge`
used, tries to prefetch new value before expire to replace cache transparently.


### memoizedFn.clear()

Remove all cached data.


## License

[MIT](https://github.com/nodeca/promise-memoize/blob/master/LICENSE)