简体   繁体   中英

Service s undefined whenever I try to call a method from it

I'm following Jogesh Muppala's Angular course on Coursera, and I'm stuck at the beginning of Week 4, where he's using HttpClient to communicate with the server.

I've followed the instructions exactly, but his instructions seem to break my program. DishServices is a service that retrieves data from the server, and is injected into one of the components, which calls on the service to do the retrieval. However, whenever that call is made, I get nothing on the page and this in the console.

MenuComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'getDishes' of undefined at MenuComponent.push../src/app/menu/menu.component.ts.MenuComponent.ngOnInit (menu.component.ts:18) at checkAndUpdateDirectiveInline (core.js:9250) at checkAndUpdateNodeInline (core.js:10514) at checkAndUpdateNode (core.js:10476) at debugCheckAndUpdateNode (core.js:11109) at debugCheckDirectivesFn (core.js:11069) at Object.eval [as updateDirectives] (MenuComponent_Host.ngfactory.js? [sm]:1) at Object.debugUpdateDirectives [as updateDirectives] (core.js:11061) at checkAndUpdateView (core.js:10458) at callViewAction (core.js:10699)

As it happens, I prefer to use the older style of writing providers, and it revealed an error there.

  providers: [{provide: DishService,                useValue: new DishService()},
          {provide: PromotionService,           useValue: new PromotionService()},
          {provide: ProcessHTTPMessageService,  useValue: new ProcessHTTPMessageService()},
          {provide: 'BaseURL',                  useValue: baseURL}
        ],

There's an error at DishService(), saying that it has the wrong number of arguments. When I check DishService,

   import {Dish} from '../shared/dish';
   import {DISHES } from '../shared/dishes';
   import {Observable, of} from 'rxjs';
   import { delay } from 'rxjs/operators';

   import { map } from 'rxjs/operators';
   import { HttpClient } from '@angular/common/http';
   import { baseURL } from '../shared/baseurl';
   import { Injectable } from '@angular/core';


   export class DishService {

  constructor(private http: HttpClient) {

   }

  getDishes(): Observable<Dish[]>{
    return this.http.get<Dish[]>(baseURL + 'dishes');

  }

}

There's the HttpClient in the constructor, which implies that it needs an object like that to be instantiated. The tutorial does not specify to to provide a new HttpClient in the providers. I have tried switching to the new style of writing providers, with Injectable providedIn root, with no success.

EDIT: Code from MenuComponent

import { Component, OnInit, Inject } from '@angular/core';
import { Dish } from '../shared/dish';
import {DishService} from '../services/dish.service';

@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.scss']
})
export class MenuComponent implements OnInit {

    dishes: Dish[];

  constructor(private dishService: DishService, @Inject('BaseURL') private BaseURL) { }

  ngOnInit() {
    console.log("fkvjndf");
     this.dishService.getDishes().subscribe(dishes => this.dishes = dishes);
  }


}

EDIT:

Replaced

  providers: [{provide: DishService,                useValue: new DishService()},
          {provide: PromotionService,           useValue: new PromotionService()},
          {provide: ProcessHTTPMessageService,  useValue: new ProcessHTTPMessageService()},
          {provide: 'BaseURL',                  useValue: baseURL}
        ],  

With

  providers: [{provide: DishService},
          {provide: PromotionService},
          {provide: ProcessHTTPMessageService},
          {provide: 'BaseURL', useValue: baseURL}
        ],  

and added

@Injectable({
  providedIn: 'root'
})

to DishService.ts

only to get the same error message

MenuComponent_Host.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'getDishes' of undefined at MenuComponent.push../src/app/menu/menu.component.ts.MenuComponent.ngOnInit (menu.component.ts:18) at checkAndUpdateDirectiveInline (core.js:9250) at checkAndUpdateNodeInline (core.js:10514) at checkAndUpdateNode (core.js:10476) at debugCheckAndUpdateNode (core.js:11109) at debugCheckDirectivesFn (core.js:11069) at Object.eval [as updateDirectives] (MenuComponent_Host.ngfactory.js? [sm]:1) at Object.debugUpdateDirectives [as updateDirectives] (core.js:11061) at checkAndUpdateView (core.js:10458) at callViewAction (core.js:10699)

The problem is that you have defined a parameter in the constructor, but when you call new DishService() you don't pass this value in. In general, you can simplify your providers section and should be able to fix your problem in the same turn.

providers: [
    DishService,
    PromotionService,,
    ProcessHTTPMessageService,
    {provide: 'BaseURL', useValue: baseURL}
],

If you don't need any special construction for your provider, you can just pass in the class and the dependency injection framework will take care of the dependencies for you.

I don't see why you should use the older style of writing providers , but if you want to make it more complicated you need to use a factory, once you require dependencies. But as I see it there is no point in doing that in your case.

I think you need to add @Injectable() decorator in your service class and also these after this code..

   import {Dish} from '../shared/dish';
   import {DISHES } from '../shared/dishes';
   import {Observable, of} from 'rxjs';
   import { delay } from 'rxjs/operators';

   import { map } from 'rxjs/operators';
   import { HttpClient } from '@angular/common/http';
   import { baseURL } from '../shared/baseurl';
   import { Injectable } from '@angular/core';

   @Injectable({
     providedIn: 'root',
   })
   export class DishService {

  constructor(private http: HttpClient) {

   }

  getDishes(): Observable<Dish[]>{
    return this.http.get<Dish[]>(baseURL + 'dishes');

  }

}

No need to place this service in provider options of NgModule decorator of root module (like : app.module) due to the 'providedIn' flag and must need to add HttpClientModule in imports options of NgModule decorator also. Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM