简体   繁体   English

RxJS 与 Angular 双向绑定多次进入 catchError

[英]RxJS with Angular Two-way binding enter multiple times in catchError

I have a service that store items in the session storage with an expiry date.我有一项服务,可以在 session 存储中存储具有到期日期的项目。 When i retrieve an item, if the expiry date is over, the service return null value:当我检索项目时,如果到期日期已过,服务返回 null 值:

The method to save items:物品保存方法:

private saveSessionData<T>(key: string, value: T) {
    const now = new Date();
    const item = {
      value: value,
      expiry: now.getTime() + 15 * 60000 // 15 minutes from now
    }
    sessionStorage.setItem(key, JSON.stringify(item));
  }

The method to retrieve items:获取物品的方法:

private getSessionData<T>(key: string): T | null {
    const itemStr = sessionStorage.getItem(key);
    if(!itemStr) return null;
    const item = JSON.parse(itemStr);
    const now = new Date();
    if (now.getTime() > item.expiry) {
      sessionStorage.removeItem(key);
      return null;
    }
    return item.value;
  }

In my controller, I access one of those value by putting them on an Observable like:在我的 controller 中,我通过将它们放在 Observable 上来访问其中一个值,例如:

const value$ = of(this.storageService.getSessionData<string>('value'))
        .pipe(
          catchError(err => {
            console.log('The session is expired');
            // ... open a modal and route the user to the home
            return err;
          })
        );

And then i display it in my view with:然后我在我的视图中显示它:

{{(value$ | async)}}

The thing I want as soon as my Stored data is expired, is to open a Modal and route the user to an other page (It is what i did in the catchError() .一旦我的存储数据过期,我想要的就是打开一个模态并将用户路由到另一个页面(这是我在catchError()中所做的。

The problem is that when my data actually expire, in the console I have multiple logs meaning i entered multiple times in my catchError() which is a problem since my openModal function is not idempotent (so it open multiple times leading to a poor user experience):问题是,当我的数据实际过期时,在控制台中我有多个日志,这意味着我在catchError()中输入了多次,这是一个问题,因为我的 openModal function 不是幂等的(因此它打开多次导致糟糕的用户体验):

console.log:控制台日志:

The session is expired
The session is expired
The session is expired
The session is expired
The session is expired

How can i change this to actually call the error function only once?我如何才能将其更改为仅调用一次错误 function ?

I tried to use throws new Error('session expired') instead of the return null;我尝试使用throws new Error('session expired')而不是return null; in my retrieve data function and put a try() catch() block in my controller, but it ended the same.在我的检索数据 function 中并在我的 controller 中放置一个 try() catch() 块,但结果相同。

Does anyone got an idea on how catch my error only once?有人知道如何只捕获一次我的错误吗?

If you have multiple value$ | async如果你有多个value$ | async value$ | async in the template, you will end up with multiple subscriptions!!!模板中的value$ | async ,您最终将获得多个订阅!

You can apply the share() operator to ensure only a single subscription is used:您可以应用share()运算符来确保只使用一个订阅:

const value$ = of(this.storageService.getSessionData<string>('value')).pipe(
  share(), 
  catchError(err => {
    console.log('The session is expired');
  })
);

As far as I see there's nothing asynchronous about the function getSessionData, you could let go of the whole of/pipe block and replace it with a simple if/else block.据我所知,function getSessionData 没有任何异步,你可以让整个 of/pipe 块的 go 并用一个简单的 if/else 块替换它。 If I'm missing something please comment.如果我遗漏了什么,请发表评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM