angularangular6angular-routerangular-resolver

Resolver does not resolve if another data stream is added


I am trying to use a resolver in order to retrieve data depending on the given parameters the route holds.

Unfortunately, the moment I add another data stream that my data depends on the resolver never actually resolves.

If I directly return an immediately resolving value everything works fine. I debugged the situation to see that I receive all partial information but it just fails to actually resolve in the end.

Here's a quick sample. Hit me up if there's more code needed to understand the problem.

MyService:

export class MyService {
  get(bar) {
    return of(new Foo(bar));
  }
}

SecondService (This one retrieves data from the backend):

export class SecondService {
  private readonly _observable: Observable<Bar>;
  constructor() {
    this._observable = merge(
      // Other manipulations
    ).pipe(
      // other manipulations
      shareReplay(1)
    )
  }

  observable(): Observable<Bar> {
    return this._observable;
  }
}

Resolver:

export class MyResolver {
  constructor(_secondService: SecondService, _myService: MyService) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Foo> {
    // Does not work - Simply does not resolve
    // return this._secondService
    //   .observable()
    //   .pipe(
    //     switchMap((bar) => this._myService.get(bar)),
    //   );

    // WORKS
    return of(new Foobar('sampleData'));
  }
}

Router:

const routes: Routes = [
  {
    path: 'someroute',
    component: SomeComponent,
    canActivate: [SomeGuard],
    resolve: {
      myData: MyResolver,
    },
  },
];

Component:

export class SomeComponent implements OnInit {
  constructor(private readonly _route: ActivatedRoute) {}

  ngOnInit() {
    this._route.data
      .subscribe((data) => {
      console.log('received:', data);
      this.myData = data;      
    });
  }
}

SomeComponent.html

<pre *ngIf="myData">
  Received: {{ myData | json }}
</pre>

Solution

  • The answer to my problem is rather simple and had nothing to do with subscribing to the resolved observables, as the framework already did that automagically.

    In order for a resolver to finish, all the streams it depends on need to complete. If you happen to use a hot observable it is required to use another operator like take so that the stream completes at that location.

    So, all the code remains the same, except that I changed the resolver to:

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Foo> {
      return this._secondService
        .observable()
        .pipe(
          take(1),
          switchMap((bar) => this._myService.get(bar)),
      );
    }
    

    @eduPeeth: Thank you for your answer/suggestions, unfortunately, it was a far more minor issue.