0

I'm literally going crazy trying to use a Resolver in Angular 6.

My Resolver, working version:

    @Injectable()
export class MyResolver implements Resolve<boolean> {
    constructor() {
    }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
        return true;
    }

I inject it like this in my routing:

path: "secure",
    component: SecureComponent,
    canActivate: [AuthGuard],
    canActivateChild: [AuthGuard],
    resolve: {
        myValue: MyResolver
    }

This works properly, the component constructor is fired and I can retrieve the myValue from the route.

But as soon as I change my resolver to:

return Observable.create(true);

Or any code that returns an Observable instead of a plain value the constructor of the component isn't fired anymore, and I get a blank page at my route. The resolver code still runs in its entirety.

I verified the constructor not being fired by placing a console.log("foo") at the very first line of the constructor, and it is not called.

So I can't understand why I can't output an observable from my resolver. The whole point of the resolvers is to resolve deferred values (thus returning observables).

What am I doing wrong?

Matteo Mosca
  • 7,380
  • 4
  • 44
  • 80

2 Answers2

3

I think the problem is that Observable.create does not complete the observable stream. Thus subscribing in your route does not emit anything. You should try something like this:

import { of } from 'rxjs/observable/of';

return of(true);

This will return a complete observable. Or you could also do:

return Observable.create((observer) => {
  observer.next(true);
  observer.complete();
    });

Let me know..

David Anthony Acosta
  • 4,766
  • 1
  • 19
  • 19
  • You... SAVIOR. The source of my observable was not completed. Not in the sample create(true) not in my real code. My observables are Subject and on those I did call "next" but not "complete". Once I added the call to "complete" everything started working perfectly. Many many thanks. – Matteo Mosca May 10 '18 at 13:51
1

Observable.create accepts a function as an argument.

Observable.create(true) will result in error on subscription. The component isn't instantiated because there is navigation error that wasn't caught.

If a resolver is supposed to return existing value, this should be done as original code shows:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    return true;
}
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • That's useful, but the real kicker was the need to call complete() on the observable. David Anthony Costa provided the right answer. – Matteo Mosca May 10 '18 at 13:56
  • That's true. This depends on why Observable.create was used, it just isn't needed in the code you've posted. – Estus Flask May 10 '18 at 14:00
  • It was a sample. From my sample the other guy showed me a complete working observable. I was missing the need to call on "complete()" to make it work. – Matteo Mosca May 10 '18 at 14:03