Skip to content

Commit

Permalink
Modernize examples in readme (#213)
Browse files Browse the repository at this point in the history
* Modernize examples in readme

* Also update examples/*
  • Loading branch information
leebyron committed Nov 13, 2019
1 parent 70f3755 commit 54f33ba
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 117 deletions.
98 changes: 52 additions & 46 deletions README.md
Expand Up @@ -53,9 +53,9 @@ Batching is not an advanced feature, it's DataLoader's primary feature.
Create loaders by providing a batch loading function.

```js
var DataLoader = require('dataloader')
const DataLoader = require('dataloader')

var userLoader = new DataLoader(keys => myBatchGetUsers(keys));
const userLoader = new DataLoader(keys => myBatchGetUsers(keys))
```

A batch loading function accepts an Array of keys, and returns a Promise which
Expand All @@ -66,14 +66,14 @@ 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.

```js
userLoader.load(1)
.then(user => userLoader.load(user.invitedByID))
.then(invitedBy => console.log(`User 1 was invited by ${invitedBy}`));
const user = await userLoader.load(1)
const invitedBy = await userLoader.load(user.invitedByID)
console.log(`User 1 was invited by ${invitedBy}`)

// Elsewhere in your application
userLoader.load(2)
.then(user => userLoader.load(user.lastInvitedID))
.then(lastInvited => console.log(`User 2 last invited ${lastInvited}`));
const user = await userLoader.load(2)
const lastInvited = await userLoader.load(user.lastInvitedID)
console.log(`User 2 last invited ${lastInvited}`)
```

A naive application may have issued four round-trips to a backend for the
Expand Down Expand Up @@ -144,9 +144,9 @@ In addition to relieving pressure on your data storage, caching results per-requ
also creates fewer objects which may relieve memory pressure on your application:

```js
var userLoader = new DataLoader(...)
var promise1A = userLoader.load(1)
var promise1B = userLoader.load(1)
const userLoader = new DataLoader(...)
const promise1A = userLoader.load(1)
const promise1B = userLoader.load(1)
assert(promise1A === promise1B)
```

Expand All @@ -172,11 +172,11 @@ function createLoaders(authToken) {
}
}

var app = express()
const app = express()

app.get('/', function(req, res) {
var authToken = authenticateUser(req)
var loaders = createLoaders(authToken)
const authToken = authenticateUser(req)
const loaders = createLoaders(authToken)
res.send(renderPage(req, loaders))
})

Expand All @@ -195,18 +195,17 @@ Here's a simple example using SQL UPDATE to illustrate.

```js
// Request begins...
var userLoader = new DataLoader(...)
const userLoader = new DataLoader(...)

// And a value happens to be loaded (and cached).
userLoader.load(4).then(...)
const user = await userLoader.load(4)

// A mutation occurs, invalidating what might be in cache.
sqlRun('UPDATE users WHERE id=4 SET username="zuck"').then(
() => userLoader.clear(4)
)
await sqlRun('UPDATE users WHERE id=4 SET username="zuck"')
userLoader.clear(4)

// Later the value load is loaded again so the mutated data appears.
userLoader.load(4).then(...)
const user = await userLoader.load(4)

// Request completes.
```
Expand All @@ -221,12 +220,14 @@ be cached to avoid frequently loading the same `Error`.
In some circumstances you may wish to clear the cache for these individual Errors:

```js
userLoader.load(1).catch(error => {
if (/* determine if should clear error */) {
userLoader.clear(1);
try {
const user = await userLoader.load(1)
} catch (error) {
if (/* determine if the error should not be cached */) {
userLoader.clear(1)
}
throw error;
});
throw error
}
```

#### Disabling Cache
Expand All @@ -244,7 +245,7 @@ for each instance of the requested key.
For example:

```js
var myLoader = new DataLoader(keys => {
const myLoader = new DataLoader(keys => {
console.log(keys)
return someBatchLoadFn(keys)
}, { cache: false })
Expand All @@ -263,7 +264,7 @@ enabled, but will immediately clear its cache when the batch function is called
so later requests will load new values.

```js
var myLoader = new DataLoader(keys => {
const myLoader = new DataLoader(keys => {
identityLoader.clearAll()
return someBatchLoadFn(keys)
})
Expand Down Expand Up @@ -310,16 +311,16 @@ Loads a key, returning a `Promise` for the value represented by that key.
Loads multiple keys, promising an array of values:

```js
var [ a, b ] = await myLoader.loadMany([ 'a', 'b' ]);
const [ a, b ] = await myLoader.loadMany([ 'a', 'b' ])
```

This is equivalent to the more verbose:

```js
var [ a, b ] = await Promise.all([
const [ a, b ] = await Promise.all([
myLoader.load('a'),
myLoader.load('b')
]);
])
```

- *keys*: An array of key values to load.
Expand Down Expand Up @@ -378,7 +379,7 @@ When using DataLoader, we could define the `User` type using the
and possibly fewer if there are cache hits.

```js
var UserType = new GraphQLObjectType({
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
name: { type: GraphQLString },
Expand All @@ -391,9 +392,12 @@ var UserType = new GraphQLObjectType({
first: { type: GraphQLInt }
},
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)))
resolve: async (user, { first }) => {
const rows = await queryLoader.load([
'SELECT toID FROM friends WHERE fromID=? LIMIT ?', user.id, first
])
return rows.map(row => userLoader.load(row.toID))
}
}
})
})
Expand All @@ -415,15 +419,15 @@ function createLoaders(authToken) {
users: new DataLoader(ids => genUsers(authToken, ids)),
cdnUrls: new DataLoader(rawUrls => genCdnUrls(authToken, rawUrls)),
stories: new DataLoader(keys => genStories(authToken, keys)),
};
}
}

// When handling an incoming web request:
var loaders = createLoaders(request.query.authToken);
const loaders = createLoaders(request.query.authToken)

// Then, within application logic:
var user = await loaders.users.load(4);
var pic = await loaders.cdnUrls.load(user.rawPicUrl);
const user = await loaders.users.load(4)
const pic = await loaders.cdnUrls.load(user.rawPicUrl)
```

Creating an object where each key is a `DataLoader` is one common pattern which
Expand All @@ -438,19 +442,21 @@ value. If the same user is loaded by both keys, then it may be useful to fill
both caches when a user is loaded from either source:

```js
let userByIDLoader = new DataLoader(ids => genUsersByID(ids).then(users => {
const userByIDLoader = new DataLoader(async ids => {
const users = await genUsersByID(ids)
for (let user of users) {
usernameLoader.prime(user.username, user);
usernameLoader.prime(user.username, user)
}
return users;
}));
return users
})

let usernameLoader = new DataLoader(names => genUsernames(names).then(users => {
const usernameLoader = new DataLoader(async names => {
const users = await genUsernames(names)
for (let user of users) {
userByIDLoader.prime(user.id, user);
userByIDLoader.prime(user.id, user)
}
return users;
}));
return users
})
```


Expand Down
20 changes: 9 additions & 11 deletions examples/CouchDB.md
Expand Up @@ -8,13 +8,13 @@ This example uses the [nano][] CouchDB client which offers a `fetch` method
supporting the bulk document API.

```js
var DataLoader = require('dataloader');
var nano = require('nano');
const DataLoader = require('dataloader');
const nano = require('nano');

var couch = nano('http://localhost:5984');
const couch = nano('http://localhost:5984');

var userDB = couch.use('users');
var userLoader = new DataLoader(keys => new Promise((resolve, reject) => {
const userDB = couch.use('users');
const userLoader = new DataLoader(keys => new Promise((resolve, reject) => {
userDB.fetch({ keys: keys }, (error, docs) => {
if (error) {
return reject(error);
Expand All @@ -25,12 +25,10 @@ var userLoader = new DataLoader(keys => new Promise((resolve, reject) => {

// Usage

var promise1 = userLoader.load('8fce1902834ac6458e9886fa7f89c0ef');
var promise2 = userLoader.load('00a271787f89c0ef2e10e88a0c00048b');

Promise.all([ promise1, promise2 ]).then(([ user1, user2]) => {
console.log(user1, user2);
});
const promise1 = userLoader.load('8fce1902834ac6458e9886fa7f89c0ef');
const promise2 = userLoader.load('00a271787f89c0ef2e10e88a0c00048b');
const [ user1, user2 ] = await Promise.all([ promise1, promise2 ])
console.log(user1, user2);
```

[nano]: https://github.com/dscape/nano
6 changes: 3 additions & 3 deletions examples/GoogleDatastore.md
Expand Up @@ -10,16 +10,16 @@ const Datastore = require('@google-cloud/datastore');

const datastore = new Datastore();

const datastoreLoader = new DataLoader(keys =>
datastore.get(keys).then(results => {
const datastoreLoader = new DataLoader(async keys => {
const results = await datastore.get(keys)
// Sort resulting entities by the keys they were requested with.
const entities = results[0];
const entitiesByKey = {};
entities.forEach(entity => {
entitiesByKey[JSON.stringify(entity[datastore.KEY])] = entity;
});
return keys.map(key => entitiesByKey[JSON.stringify(key)] || null);
}),
},
{
// Datastore complex keys need to be converted to a string for use as cache keys
cacheKeyFn: key => JSON.stringify(key),
Expand Down
10 changes: 5 additions & 5 deletions examples/Knex.md
Expand Up @@ -14,7 +14,7 @@ const db = require('./db'); // an instance of Knex client

// The list of data loaders

const data = {
const loaders = {
user: new DataLoader(ids => db.table('users')
.whereIn('id', ids).select()
.then(rows => ids.map(id => rows.find(x => x.id === id)))),
Expand All @@ -30,10 +30,10 @@ const data = {

// Usage

Promise.all([
data.user.load('1234'),
data.storiesByUserId.load('1234'),
]).then(([user, stories]) => {/* ... */});
const [user, stories] = await Promise.all([
loaders.user.load('1234'),
loaders.storiesByUserId.load('1234'),
])
```

For a complete example visit [kriasoft/nodejs-api-starter][nsk].
Expand Down
8 changes: 4 additions & 4 deletions examples/Redis.md
Expand Up @@ -7,12 +7,12 @@ with DataLoader.
Here we build an example Redis DataLoader using [node_redis][].

```js
var DataLoader = require('dataloader');
var redis = require('redis');
const DataLoader = require('dataloader');
const redis = require('redis');

var client = redis.createClient();
const client = redis.createClient();

var redisLoader = new DataLoader(keys => new Promise((resolve, reject) => {
const redisLoader = new DataLoader(keys => new Promise((resolve, reject) => {
client.mget(keys, (error, results) => {
if (error) {
return reject(error);
Expand Down

0 comments on commit 54f33ba

Please sign in to comment.