rxjs-data-loader

This package create cached queries to avoid make duplicate requests to the backend.


License
ISC
Install
npm install rxjs-data-loader@1.0.7

Documentation

RXJS Data Loader

This package create cached queries to avoid make duplicate requests to the backend. The sample below is self explanatory (we reduce 121 queries to just 4 using this package):

Usage with GraphQL

	const users = [{
	    id: 0,
	    name: 'Philip'
	}, {
	    id: 1,
	    name: 'David'
	}, {
	    id: 2,
	    name: 'John'
	}, {
	    id: 3,
	    name: 'George'
	}];

	const friendsOf = [
	    [1, 2, 3],
	    [0, 2, 3],
	    [0, 1, 3],
	    [0, 1, 2]
	];

	const getUser = sinon.spy(id => new Observable(subscriber => {
	    if (!users[id]) {
	        subscriber.error(new Error('no user id'));
	    }

	    subscriber.next(users[id]);
	    subscriber.complete();
	})
	.pipe(
		share()
	));

	const User = new GraphQLObjectType({
	    name: 'User',
	    fields: () => ({
	        name: {
	            type: GraphQLString
	        },
	        friends: {
	            type: new GraphQLList(User),
	            resolve: ({
	                id
	            }, args, context) => {
	                const {
	                    userLoader
	                } = context;

	                return from(friendsOf[id])
						.pipe(
							mergeMap(id => userLoader ? userLoader.get(id) : getUser(id)).
	                    	toArray()
						)
	                    .toPromise();
	            }
	        }
	    })
	});

	const schema = new GraphQLSchema({
	    query: new GraphQLObjectType({
	        name: 'Query',
	        fields: {
	            user: {
	                type: User,
	                args: {
	                    id: {
	                        type: new GraphQLNonNull(GraphQLInt)
	                    },
	                    useLoader: {
	                        type: GraphQLBoolean
	                    }
	                },
	                resolve: (root, {
	                    id,
	                    useLoader
	                }, context, info) => {
	                    if (useLoader) {
	                        const userLoader = context.userLoader = new DataLoader(getUser);

	                        return userLoader.get(id)
	                            .toPromise();
	                    }

	                    return getUser(id)
	                        .toPromise();
	                }
	            }
	        }
	    })
	});

	const asyncGraph = requestString => from(graphql(schema, requestString, {}, {}))
		.pipe(
			tap(response => {
				if (response.errors) {
					throw new Error(response.errors.join());
				}
			})
		);

	const query = (id, useLoader = false) => `{
	    user(id: ${id}, useLoader: ${useLoader}) {
	        name
	        friends {
	            name
	            friends {
	                name
	                friends {
	                    name
	                    friends {
	                        name
	                    }
	                }
	            }
	        }
	    }
	}`;

	asyncGraph(query(0))
            .subscribe(null, null, () => {
                // getUser will be called 121 times
            });

	asyncGraph(query(0, true))
            .subscribe(null, null, () => {
                // getUser will be called 4 times, once per user ;)
            });