Angular RxJS:为什么订阅没有区别

Angular RxJS:为什么订阅没有区别,angular,unit-testing,rxjs,observable,jasmine-marbles,Angular,Unit Testing,Rxjs,Observable,Jasmine Marbles,考虑下面的服务示例 export class AuthService { private observableCache: { [key: string]: Observable<boolean> } = {}; private resourceCache: { [key: string]: boolean } = {}; constructor(private userService: UserService) { } isGranted(resource):

考虑下面的服务示例

export class AuthService {
  private observableCache: { [key: string]: Observable<boolean> } = {};
  private resourceCache: { [key: string]: boolean } = {};

  constructor(private userService: UserService) { }

  isGranted(resource): Observable<boolean> {
    if (this.resourceCache[resource]) {
      return of(this.resourceCache[resource]);
    }

    if (this.observableCache[role]) {
      return this.observableCache[role];
    }

    this.observableCache[resource] = this.userService
        .getCurrentUser()
        .pipe(map((user: User) => user.canAccess(resource)))
        .pipe(share());

    return this.observableCache[resource];
  }
}
测试的目的是检查资源缓存是否工作。但我注意到,如果我替换以下代码段

  service.isGranted('dashboard').subscribe();
  service.isGranted('dashboard').subscribe();
简单的

  service.isGranted('dashboard');
  service.isGranted('dashboard');
测试仍然有效,我对RxJS和大理石测试还不熟悉,但据我所知,Observable应该在订阅之前不起作用


问题-为什么它是双向的?

测试使用的代码是异步的,请尝试使用
fakeAsync
勾选

it('should prove response being cached', fakeAsync(() => {
  service.isGranted('dashboard').subscribe();
  service.isGranted('dashboard').subscribe();
  tick();
  expect(userService.getCurrentUser).toHaveBeenCalledTimes(1);
}));

查看以获取更多信息。

您不是在测试是否创建了可观察链。您只是在测试是否调用了
userService.getCurrentUser
,并且每次调用
isgrated
时都会调用它。所以这与RxJS无关。为什么执行
userService.getCurrentUser
而不强制执行订阅?正如我从RxJS文档中得到的,计算只对订阅的每个观察者进行,它与RxJS无关。调用
isgrated
时调用该方法,就像任何其他JavaScript代码中的任何其他方法一样。@martin您能提供一个该测试的示例吗?谢谢,谢谢!这个测试用例通过了,我也通过了!请你扩展你的答案并解释一下好吗?现在,我正在寻找一个答案,而不是代码片段,而是JavaScript中的事件循环,特别是宏和微任务。在异步调用中,Javascript可能会在任务之间“切换”,因此您不知道何时执行哪个任务。“service.isgrated('dashboard').subscribe()”启动一个微任务。使用“fakeAsync”,您可以将整个代码放入一种沙箱中。使用“tick()”命令沙箱执行所有打开的微任务。如果您不这样做,您的单元测试可能会在执行微任务之前完成。。热烈问候简
it('should prove response being cached', fakeAsync(() => {
  service.isGranted('dashboard').subscribe();
  service.isGranted('dashboard').subscribe();
  tick();
  expect(userService.getCurrentUser).toHaveBeenCalledTimes(1);
}));