【问题标题】:how to replace synchronous local-storage with asynchronous Indexed-db for Angular App如何用 Angular App 的异步 Indexed-db 替换同步本地存储
【发布时间】:2020-05-10 03:45:55
【问题描述】:

我正在使用本地存储来获取数据,如果本地存储上没有数据,则进行服务器 API 调用并将数据添加到存储以供将来使用,然后返回数据。所以下次它会从存储中返回数据,而不是从 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 获取数据返回承诺)。

【问题讨论】:

  • 先做两件事:1) 当你想从同步数据创建一个 observable 时使用of(result)。 2) 当您返回完全相同的对象时,使用map 运算符似乎很奇怪。你应该改用tap

标签: angular local-storage indexeddb


【解决方案1】:

您必须使用 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.');
                           })
                         );
          }
        })
    );

【讨论】:

  • 非常感谢,它非常有效。你知道什么是学习 RxJs 的好资源吗?
  • 对不起,我没有。但是google肯定有很多关于它的教程,因为它是Angular中广泛使用的库。
猜你喜欢
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 2020-11-03
  • 2017-08-03
  • 2010-09-19
  • 2014-10-19
  • 2015-06-14
  • 1970-01-01
相关资源
最近更新 更多