7

I have a resolve that fetches data from an api and a service that depends on that resolve. The service depending on the resolve will be providing sections of data to multiple components and is only expected to be run once when the page loads. Here is the relevant code (imports & some annotations omitted):

product-details.service.ts

@Injectable()
export class ProductDetailsService {
    private productDetails: ProductDetails;

    constructor(route: ActivatedRoute) {
        this.productDetails = route.snapshot.data['product'];
    }

    public getProductDetails(): ProductDetails {
        return this.productDetails;
    }
}

product-details.resolve.ts

@Injectable()
export class ProductDetailsResolve implements Resolve<ProductDetails> {

    constructor(private httpService: HttpService) { }

    resolve(route: ActivatedRouteSnapshot): Observable<ProductDetails> {
        return this.httpService.getProductDetails(route.params['id']);
    }

}

app-routing.module.ts

const routes: Routes = [
    { path: 'main/:id', component: MainComponent, resolve: { product: ProductDetailsService } },
];

@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

some.component.ts

export class SomeComponent {
    public value: number = 0;

    constructor(private productDetailsService: ProductDetailsService) {
        this.value = productDetailsService.getProductDetails().value;
    }

}

When I run the app, I get this error:

core.es5.js:1020 ERROR Error: Uncaught (in promise): TypeError: resolver is not a function
TypeError: resolver is not a function
    at PreActivation.webpackJsonp.../../../router/@angular/router.es5.js.PreActivation.getResolver (router.es5.js:4559)
    at PreActivation.webpackJsonp.../../../router/@angular/router.es5.js.PreActivation.resolveNode (router.es5.js:4537)
    at PreActivation.webpackJsonp.../../../router/@angular/router.es5.js.PreActivation.runResolve (router.es5.js:4518)
    at MergeMapSubscriber.project (router.es5.js:4285)
    at MergeMapSubscriber.webpackJsonp.../../../../rxjs/operator/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:120)
    at MergeMapSubscriber.webpackJsonp.../../../../rxjs/operator/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:110)
    at MergeMapSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
    at ArrayObservable.webpackJsonp.../../../../rxjs/observable/ArrayObservable.js.ArrayObservable._subscribe (ArrayObservable.js:114)
    at ArrayObservable.webpackJsonp.../../../../rxjs/Observable.js.Observable._trySubscribe (Observable.js:171)
    at ArrayObservable.webpackJsonp.../../../../rxjs/Observable.js.Observable.subscribe (Observable.js:159)
    at PreActivation.webpackJsonp.../../../router/@angular/router.es5.js.PreActivation.getResolver (router.es5.js:4559)
    at PreActivation.webpackJsonp.../../../router/@angular/router.es5.js.PreActivation.resolveNode (router.es5.js:4537)
    at PreActivation.webpackJsonp.../../../router/@angular/router.es5.js.PreActivation.runResolve (router.es5.js:4518)
    at MergeMapSubscriber.project (router.es5.js:4285)
    at MergeMapSubscriber.webpackJsonp.../../../../rxjs/operator/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:120)
    at MergeMapSubscriber.webpackJsonp.../../../../rxjs/operator/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:110)
    at MergeMapSubscriber.webpackJsonp.../../../../rxjs/Subscriber.js.Subscriber.next (Subscriber.js:89)
    at ArrayObservable.webpackJsonp.../../../../rxjs/observable/ArrayObservable.js.ArrayObservable._subscribe (ArrayObservable.js:114)
    at ArrayObservable.webpackJsonp.../../../../rxjs/Observable.js.Observable._trySubscribe (Observable.js:171)
    at ArrayObservable.webpackJsonp.../../../../rxjs/Observable.js.Observable.subscribe (Observable.js:159)
    at resolvePromise (zone.js:795)
    at resolvePromise (zone.js:766)
    at zone.js:844
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
    at Object.onInvokeTask (core.es5.js:3881)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (zone.js:192)
    at drainMicroTaskQueue (zone.js:602)
    at <anonymous>

Research into this error has not given me any clues, and I can't think of any reason why the resolve is not being acknowledged as a function. Is there something that I am missing here?

4
  • 1
    You've configured ProductDetailsService as your resolver in the route definition instead of configuring ProductDetailsResolve. Commented Oct 25, 2017 at 22:57
  • So I did. Good catch! I made the change, but I'm now getting ERROR Error: Uncaught (in promise): Error: No provider for ProductDetailsResolve! Will update the question Commented Oct 25, 2017 at 23:01
  • Just read the error message. It tells you that you have no provider for the ProductDetailsResolve service. Have you added this service to the providers array of your NgModule? Commented Oct 25, 2017 at 23:02
  • Made that change, too. I'm new to Angular, so I'm still having trouble remembering to update everything/where I have to update. Commented Oct 25, 2017 at 23:06

3 Answers 3

5

I got this error when I accidentally passed a Guard as a resolver in my route config:

resolve: { data: MyGuardService }

So check that you haven't accidentally passed the wrong class. For example, if you want a canActivate guard, the code would look like this instead:

canActivate: [ MyGuardService ]
Sign up to request clarification or add additional context in comments.

2 Comments

This was my problem.
Yup! I provided a similarly-named Service when I meant to provide a Resolver within the route config. Thanks!
2

I received this error in Angular 8 because I forgot to implement the Resolve<T> interface in my resolver class. I.e. I had to change:

@Injectable({
    providedIn: 'root'
}
export class FooResolverService {
    // ...
}

to

@Injectable({
    providedIn: 'root'
}
export class FooResolverService implements Resolve<Foo> {
    // ...
}

Comments

1

You need to declare your ProductDetailsResolve as a provider of your AppRoutingModule, like this:

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [ProductDetailsResolve]
})

Remember to import ProductDetailsResolve on your AppRoutingModule

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.