dataloader
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -15,3 +15,4 @@ | ||
// Optionally turn off batching or caching. | ||
// Optionally turn off batching or caching or provide a cache key function or a | ||
// custom cache instance. | ||
Object.defineProperty(exports, '__esModule', { | ||
@@ -26,3 +27,3 @@ value: true | ||
/** | ||
A `DataLoader` creates a public API for loading data from a particular | ||
* A `DataLoader` creates a public API for loading data from a particular | ||
* data back-end with unique keys such as the `id` column of a SQL table or | ||
@@ -46,3 +47,3 @@ * document name in a MongoDB database, given a batch loading function. | ||
this._options = options; | ||
this._promiseCache = new Map(); | ||
this._promiseCache = options && options.cacheMap || new Map(); | ||
this._queue = []; | ||
@@ -92,6 +93,11 @@ } | ||
var shouldCache = !options || options.cache !== false; | ||
var cacheKeyFn = options && options.cacheKeyFn; | ||
var cacheKey = cacheKeyFn ? cacheKeyFn(key) : key; | ||
// If caching and there is a cache-hit, return cached Promise. | ||
if (shouldCache && this._promiseCache.has(key)) { | ||
return this._promiseCache.get(key); | ||
if (shouldCache) { | ||
var cachedPromise = this._promiseCache.get(cacheKey); | ||
if (cachedPromise) { | ||
return cachedPromise; | ||
} | ||
} | ||
@@ -101,9 +107,9 @@ | ||
var promise = new Promise(function (resolve, reject) { | ||
// Enqueue this Promise to be dispatched, and determine if a new dispatch | ||
// needs to be created: if this is the first enqueue upon an empty queue. | ||
var needsDispatch = _this._queue.length === 0; | ||
// Enqueue this Promise to be dispatched. | ||
_this._queue.push({ key: key, resolve: resolve, reject: reject }); | ||
if (needsDispatch) { | ||
// Determine if a dispatch of this queue should be scheduled. | ||
// A single dispatch should be scheduled per queue at the time when the | ||
// queue changes from "empty" to "full". | ||
if (_this._queue.length === 1) { | ||
if (shouldBatch) { | ||
@@ -123,3 +129,3 @@ // If batching, schedule a task to dispatch the queue. | ||
if (shouldCache) { | ||
this._promiseCache.set(key, promise); | ||
this._promiseCache.set(cacheKey, promise); | ||
} | ||
@@ -163,3 +169,5 @@ | ||
value: function clear(key) { | ||
this._promiseCache['delete'](key); | ||
var cacheKeyFn = this._options && this._options.cacheKeyFn; | ||
var cacheKey = cacheKeyFn ? cacheKeyFn(key) : key; | ||
this._promiseCache['delete'](cacheKey); | ||
return this; | ||
@@ -166,0 +174,0 @@ } |
{ | ||
"name": "dataloader", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "A data loading utility to reduce requests to a backend via batching and caching.", | ||
@@ -33,3 +33,3 @@ "contributors": [ | ||
"preversion": ". ./resources/checkgit.sh && npm test", | ||
"_prepublish": ". ./resources/prepublish.sh" | ||
"prepublish": ". ./resources/prepublish.sh" | ||
}, | ||
@@ -46,12 +46,12 @@ "files": [ | ||
"babel-core": "5.8.22", | ||
"babel-eslint": "4.0.10", | ||
"chai": "3.2.0", | ||
"coveralls": "2.11.3", | ||
"eslint": "1.1.0", | ||
"eslint-plugin-babel": "^2.1.1", | ||
"flow-bin": "0.14.0", | ||
"babel-eslint": "4.1.6", | ||
"chai": "3.4.1", | ||
"coveralls": "2.11.6", | ||
"eslint": "1.10.3", | ||
"eslint-plugin-babel": "2.2.0", | ||
"flow-bin": "0.20.1", | ||
"isparta": "3.0.3", | ||
"mocha": "2.2.5", | ||
"sane": "1.1.3" | ||
"mocha": "2.3.4", | ||
"sane": "1.3.0" | ||
} | ||
} |
@@ -31,4 +31,5 @@ # DataLoader | ||
DataLoader assumes a JavaScript environment with global ES6 `Promise` and `Map` | ||
classes, available in the recent versions of node.js or when using [babel][]. | ||
If your environment does not have these, provide them before using DataLoader. | ||
classes, available in the recent versions of node.js or when using | ||
[babel/polyfill][]. If your environment does not have these, provide them before | ||
using DataLoader. | ||
@@ -45,3 +46,3 @@ ```js | ||
Batching is a not an advanced feature, it's DataLoader's primary feature. | ||
Batching is not an advanced feature, it's DataLoader's primary feature. | ||
Create loaders by providing a batch loading function. | ||
@@ -58,4 +59,5 @@ | ||
Then load individual values from the loader. In this example, we're illustrating | ||
two parts of an example application which shows who was invited by whom. | ||
Then load individual values from the loader. DataLoader will coalesce all | ||
individual loads which occur within a single frame of execution (a single tick | ||
of the event loop) and then call your batch function with all requested keys. | ||
@@ -155,2 +157,9 @@ ```js | ||
- *cacheKeyFn*: A function to produce a cache key for a given load key. | ||
Defaults to `key => key`. Useful to provide when JavaScript objects are keys | ||
and two similarly shaped objects should be considered equivalent. | ||
- *cacheMap*: An instance of [Map][] (or an object with a similar API) to be | ||
used as the underlying cache for this loader. Default `new Map()`. | ||
##### `load(key)` | ||
@@ -241,6 +250,6 @@ | ||
}, | ||
type: new GraphQLList(UserType) | ||
resolve (user, { first }) => queryLoader.load([ | ||
'SELECT toID as id FROM friends WHERE fromID=? LIMIT ?', user.id, first | ||
]).then(rows => rows.map(row => userLoader.load(row.friendID))) | ||
type: new GraphQLList(UserType), | ||
resolve: (user, { first }) => queryLoader.load([ | ||
'SELECT toID FROM friends WHERE fromID=? LIMIT ?', user.id, first | ||
]).then(rows => rows.map(row => userLoader.load(row.toID))) | ||
} | ||
@@ -281,2 +290,12 @@ }) | ||
## Custom Caches | ||
DataLoader can optionaly be provided a custom Map instance to use as its | ||
cache. More specifically, any object that implements the methods `get()`, | ||
`set()`, `delete()` and `clear()` can be provided. This allows for custom Maps | ||
which implement various [cache algorithms][] to be provided. By default, | ||
DataLoader uses the standard [Map][] which simply grows until the DataLoader | ||
is released. | ||
## Common Back-ends | ||
@@ -295,3 +314,3 @@ | ||
var DataLoader = require('dataloader'); | ||
var redis = require("redis"); | ||
var redis = require('redis'); | ||
@@ -309,3 +328,3 @@ var client = redis.createClient(); | ||
}); | ||
}); | ||
})); | ||
``` | ||
@@ -368,5 +387,3 @@ | ||
rows => ids.map( | ||
id => rows.find( | ||
row => row.id === id) || new Error(`Row not found: ${id}` | ||
) | ||
id => rows.find(row => row.id === id) || new Error(`Row not found: ${id}`) | ||
) | ||
@@ -405,7 +422,9 @@ ); | ||
[@schrockn]: https://github.com/schrockn | ||
[Map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map | ||
[graphql-js]: https://github.com/graphql/graphql-js | ||
[cache algorithms]: https://en.wikipedia.org/wiki/Cache_algorithms | ||
[express]: http://expressjs.com/ | ||
[babel]: http://babeljs.io/ | ||
[babel/polyfill]: https://babeljs.io/docs/usage/polyfill/ | ||
[node_redis]: https://github.com/NodeRedis/node_redis | ||
[nano]: https://github.com/dscape/nano | ||
[sqlite3]: https://github.com/mapbox/node-sqlite3 |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
28094
226
421