P
P
pomaz_andrew2020-01-22 11:50:26
Angular
pomaz_andrew, 2020-01-22 11:50:26

Why is indexedDB not being written to?

In an Angular application, we use an IndexedDB based cache. Let's look at the issue of performance. There is no record in a DB, the reason is not clear. When trying to read objects, an empty array is returned. I bring the source code.

export class AppComponent implements OnInit {
  private _totalTime: number = 0;
  private _writeCount: number;
  private _readCount: number;
  private _db: any;
  private _books: any;

  constructor(private _httpService: HttpClient) {
  }

ngOnInit() {
    let req = indexedDB.open('store', 2);
    req.onupgradeneeded = () => { 
      this._db = req.result;
      if (!this._db.objectStoreNames.contains('store')) {
        this._db.createObjectStore('stations');
      }
    };
    req.onsuccess = () => {
      this._db = req.result;
    }
  }

  save() {
    let stations: any;
    let transaction: any;
    this._httpService.get(`/scripts/getStations.php`).subscribe(
      (resp: any) => {
        transaction = this._db.transaction('stations', "readwrite");
        stations = transaction.objectStore('stations');
        let i = 0;
        resp.forEach((item: any) => {
          i++;
          stations.add(item, i);
        });
        transaction.commit();
      });
  }

  read() {
    let transaction = this._db.transaction('stations', "readonly");
    let stations = transaction.objectStore('stations');
    let request = stations.getAll();
    request.onsuccess = function () {
      if (request.result !== undefined) {
        console.log("данные чтения =", request.result);
      }
      else {
        console.log("Ошибка чтения");
      }
    };
  };

What am I doing wrong? Thank you.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Shvets, 2020-01-22
@Xuxicheta

In appearance, everything seems to be ok, you need to debug it, move it somewhere into the sandbox.
While I can offer my own wrapper for indexedDB, it seems to work, I haven’t really tested it. Might make you think.

export interface DbConfig {
  /** prefix for indexed db name */
  name: string;
  /** keyPath in indexed db */
  keyPath?: string;
  /** keyPath of indexed db */
  objectName: string;
}

@Injectable()
export class DbService<T = any> {
  private version = 1;
  private db$: Observable<IDBDatabase> = this.createDb(this.config.name, this.version);

  constructor(
    @Inject(DB_CONFIG) private config: DbConfig,
  ) { }

  private createDb(name: string, version?: number): Observable<IDBDatabase> {
    const openRequest: IDBOpenDBRequest = indexedDB.open(name, version);

    openRequest.onupgradeneeded = (evt: IDBVersionChangeEvent) => this.onUpgradeNeeded(openRequest);

    return this.fromIDBRequest(openRequest).pipe(
      shareReplay(1),
    );
  }

  private onUpgradeNeeded(openRequest: IDBOpenDBRequest): void {
    const db = openRequest.result;
    if (db.objectStoreNames.contains(this.config.objectName)) {
      return;
    }
    db.createObjectStore(this.config.objectName, { keyPath: this.config.keyPath });
  }

  public save(value: T, key?: IDBValidKey): Observable<IDBValidKey> {
    return this.db$.pipe(
      mergeMap((db: IDBDatabase) => this.fromIDBRequest(
        this.createIDBObjectStore(db, 'readwrite').put(value, key)
      )),
    );
  }

  public saveAll(values: T[]): Observable<IDBValidKey[]> {
    return from(values).pipe(
      mergeMap((value: T, index: number) => this.save(value, index)),
      toArray(),
    );
  }

  public delete(key: string): Observable<undefined> {
    return this.db$.pipe(
      mergeMap(db => this.fromIDBRequest(
        this.createIDBObjectStore(db, 'readwrite').delete(key),
      ))
    );
  }

  public clear() {
    return this.db$.pipe(
      mergeMap(db => this.fromIDBRequest(
        this.createIDBObjectStore(db, 'readwrite').clear(),
      ))
    );
  }

  public retreive(key: string): Observable<T> {
    return this.db$.pipe(
      mergeMap(db => this.fromIDBRequest(
        this.createIDBObjectStore(db, 'readonly').get(key)
      )),
    );
  }

  public retreiveAll(): Observable<T[]> {
    return this.db$.pipe(
      mergeMap(db => this.fromIDBRequest(
        this.createIDBObjectStore(db, 'readonly').getAll()
      )),
    );
  }

  private createIDBObjectStore(db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore {
    const transaction: IDBTransaction = db.transaction(this.config.objectName, mode);
    return transaction.objectStore(this.config.objectName);
  }

  private fromIDBRequest<R>(idbRequest: IDBRequest<R>): Observable<R> {
    return new Observable<R>(observer => {
      idbRequest.onsuccess = (evt: Event) => {
        observer.next(idbRequest.result);
        observer.complete();
        evt.stopPropagation();
      };
      idbRequest.onerror = (evt: Event) => {
        observer.error(idbRequest.error);
        evt.stopPropagation();
      };
    });
  }

  public selectDb() {
    return this.db$;
  }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question