Класс Angular 2 без Http в параметрах конструктора

У меня есть класс API:

export class ApiService {

  constructor(public http: Http) { }

  put(controller: string, method: string, data: Object) {

    return this.http.put("http://127.0.0.1:8000",
      JSON.stringify(data), {
      })

    .map(res => res.json())

    .catch(err => {
      return Observable.throw(err.json());
    });

  }

}

и класс AccountService:

export class AccountService {

  api: ApiService;

  constructor() {
    this.api = new ApiService();
  }

  login(username: string, password: string) {

    return this.api.put("accounts", "login", { username: username, password: password});

  }

}

Однако, когда я запускаю этот пример, возникают две проблемы:

1) ApiService нужен http в конструкторе. Поэтому this.api = new ApiService(); должен предоставить Http, чего я не хочу.

Как я могу изменить ApiService, чтобы мне не нужно было предоставлять Http конструктору?

2) В AccountService метод this.api.put не найден на ApiService. Чего я не понимаю, так как я создал экземпляр ApiService в this.api


person Bas van Dijk    schedule 22.01.2016    source источник
comment
Совершенно непонятно, чего вы пытаетесь добиться. Если вам нужно Http сделать запрос, то как вы на самом деле хотите, чтобы он был передан ApiService? Почему вы не хотите, чтобы Http передавался DI?   -  person Günter Zöchbauer    schedule 22.01.2016
comment
СОВЕРШЕННО ясно, чего он хочет. У меня самого такой же вопрос.   -  person Lucio Mollinedo    schedule 22.09.2016


Ответы (1)


На самом деле вы можете получить экземпляр из ApiService в AccountService через внедрение зависимостей:

export class AccountService {
  constructor(private api: ApiService) {
  }
}

Вам просто нужно зарегистрировать оба сервиса:

bootstrap(AppComponent, [AccountService, ApiService]);

В противном случае я не вижу причин, по которым вы не можете использовать метод put ApiService из AccountService.

Надеюсь, это поможет вам, Тьерри.

person Thierry Templier    schedule 22.01.2016
comment
Хорошо, но таким образом я получаю массив из сотен сервисов для регистрации. Я использую UpgradeAdapter, где загрузчик выглядит так: adapter.bootstrap(document.body, ["app"]); Я пытался добавить его в качестве провайдера, но AccountService не видит ApiService. Спасибо! - person Bas van Dijk; 22.01.2016
comment
В этом случае следует попробовать использовать метод adapter.addProvider. Я думаю, что можно предоставлять сразу массив провайдеров вместо одного в каждый момент времени (см. .co/edit/PRFgtXaCVEHGc1PSDbdc?p=info). Это то, как сам Angular2 предоставляет провайдеров (например, HTTP_PROVIDERS, ROUTER_PROVIDERS). - person Thierry Templier; 22.01.2016
comment
Вроде работает!:) Но только когда добавляю с провайдером и использую import {ApiService} from "./ApiService"; в AccountService. Зачем нужны оба? Какие-нибудь мысли? - person Bas van Dijk; 22.01.2016
comment
На самом деле это две разные вещи. Вы используете класс, поэтому вам нужно его импортировать (поведение TypeScript). Экземпляр этого класса предоставляется посредством внедрения зависимостей Angular2. Так что вам нужны оба ;-) - person Thierry Templier; 22.01.2016
comment
Если вы хотите узнать больше о том, как работает внедрение зависимостей в Angular2, вы можете взглянуть на этот ответ: stackoverflow.com/questions/34804298/ ;-) - person Thierry Templier; 22.01.2016
comment
Ясно, иначе я импортирую сам класс, а не экземпляр. Поэтому мне нужно было добавить его в загрузчик, чтобы получить экземпляр синглтона? - person Bas van Dijk; 22.01.2016
comment
В яблочко! Angular2 нуждается в провайдере, чтобы иметь возможность создать экземпляр класса. Поэтому вам нужно зарегистрировать его для этого конкретного класса. На самом деле bootstrap(SomeComp, [ AccountService ]); — это сокращение от bootstrap(SomeComp, [ provide(AccountService, { useClass: AccountService }) ]);. Возможно, это проще понять с функцией provide... - person Thierry Templier; 22.01.2016