function cache<Query, Result>(
    factory: (query: Query) => Observable<Result>,
    cache: Map<Query, Result> = new Map()): (query: Query) =>
    Observable<Result> {
  const subject = new Subject<Result>();
  return query => {
    if (cache.has(query)) {
      subject.next(cache.get(query));
    } else {
      factory(query).subscribe(results => {
        cache.set(query, results);
        subject.next(results);
      });
    }
    return subject.asObservable();
  };
}