如何用 Angular 应用程序的异步 Indexed-db 替换同步本地存储

how to replace synchronous local-storage with asynchronous Indexed-db for Angular App

我正在使用本地存储获取数据,如果数据在本地存储上不可用,则调用服务器 API 并将数据添加到存储以供将来使用,然后 return 输入数据。所以下次它将 return 来自存储的数据而不是来自 API 调用的数据。

我有通用功能来完成这项工作,一切正常。

 getData(host,url):Observable<any> {
    const serverurl = host + url;
    const apiname = url.indexOf('?') !== -1 ? url.substring(1, url.indexOf('?')) : url.substring(1, url.length);
    const params = url.indexOf('?') !== -1 ? url.substring(url.indexOf('?') + 1, url.length) : '';
    var t0 = performance.now();
    var result = null ;
    result = this.GetStorageEx(apiname, params);
    if (result) 
    {
      var t1 = performance.now()
      console.log(apiname + ' returned from storage. time taken:' + (t1 - t0) + ' milliseconds.');
      return new Observable(observer => {observer.next(result);observer.complete();})
    } 
    else 
    {
       return this.getDataFromServer(serverurl).pipe(map(
        result => {
          this.UpdateStorageEx(apiname,result, params);
          var t1 = performance.now()
          console.log(apiname + ' returned from server. time taken:' + (t1 - t0) + ' milliseconds.');
          return result;
        },
        err => {
          console.log(err);
        }
     ));
   }
  }

此处 GetStorageEx 是同步调用,因此如果结果为空,我可以调用服务器 API。

由于本地存储在数据大小方面的限制,我决定使用IndexedDB,但我看到它异步调用获取数据。

所以我的问题是我应该如何修改函数 getData 以使该函数的调用者无需更改并且该函数的行为将保持不变。唯一预期的变化是 GetStorageEx 而不是从本地存储获取,我需要从 IndexedDB 获取它。 (从 IndexedDB return 承诺获取数据)。

您必须使用 RxJs 链接可观察对象:

 getData(host,url):Observable<any> {
    // stuff
    var t0 = performance.now();
    this.GetDataFromDb(...).pipe(
        switchMap(dbData => {
          if(dbData && dbData.length > 0) {
            // data found in DB, return it ("of" trick to have the same behavior as the else statement)
            return of(dbData)
          } else {
            // no data in DB, let's call the server
            // switch from DB observable to Server observable
            return this.getDataFromServer(serverurl).pipe(
                           tap(serverData => {
                             this.UpdateDbEx(apiname,result, params).subscribe(); // empty subscribe if writing in DB is async
                             var t1 = performance.now()
                             console.log(apiname + ' returned from server. time taken:' + (t1 - t0) + ' milliseconds.');
                           })
                         );
          }
        })
    );