拦截函数调用,返回Observable以显示加载指示符

时间:2018-06-14 10:27:03

标签: javascript angular rxjs

在我的Angular应用程序中,有时我需要阻止UI,同时一些HTTP请求正在运行,我想通过这样的(或类似的)API实现这一点

userService.block(elementId).getUser().subscribe();

我希望组件决定何时以及应该阻止什么以及服务内部的功能独立于此阻塞机制。

现在我必须做类似

的事情
blockService.block(elementId);
userService.getUser().subscribe(()=>blockService.unBlock(elementId));

我不想在这里使用HttpInterceptor,因为在这种情况下,我需要更新我的函数以将请求调用标记为可阻止(例如带有元素选择器的自定义标头)以在拦截器内过滤它们。

我成功实现了基于ES6代理的实现。我为具有块功能的服务创建了一个基类。但是,但总是IE - 它不适用于IE11 实施草案:

block(selector: string) {
    return new Proxy(this, {
      get: (target, propKey) => {
        let member = target[propKey];

        return (...args) => {
          this.blockService.blockUi(selector);
          let result = member.apply(target, args);

          result.subscribe(() => target.blockService.unblockUi(selector));
          return result;
        };
      }
    });
  }

任何想法如何在没有代理的情况下做到这一点?

PS。使用函数包装器的方式看起来不太好:

blockService.block(userService.getUser).subscribe()

但如果我找不到流利的方式,我将不得不使用它。

1 个答案:

答案 0 :(得分:0)

虽然可以扩展Observable的原型(API与问题略有不同,但想法是相同的 - 不需要在之前和之后调用两次),这是可能的。

TypeScript实现(对于您不需要模块声明的plaine JS):

declare module 'rxjs/Observable' {
  interface Observable<T> {
    block(blockService: UiBlockerService, elementId?: string): Observable<T>;
  }
}

Observable.prototype.blockUi = function <T>(blockService: UiBlockerService, elementId?: string) {
  blockService.block(elementId);
  const observable = this as Observable<T>;

  return observable.pipe(finalize(() => blockService.unblockUi(elementId)));
};

用法:

userService.getUser().block(uiBlocker, elementId).subscribe();

如果要在处理来自Observable的数据时阻止/显示微调器,请在运算符(map,tap等)之后调用block()非常重要。

相关问题