Как внедрить службу Angular2 Http в класс es6/7?

Если я использую es6/7 (babel - этап 1) вместо TypeScript, как внедряются службы, и в частности Http?

Вот мой компонент JS:

import {Component, Inject, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2';
import {Http} from 'angular2/http';

@Component({
  selector: 'login'
})
@View({
  templateUrl: './components/login/login.html',
  styleUrls: ['components/login/login.css'],
  directives: [CORE_DIRECTIVES],
  encapsulation: ViewEncapsulation.Emulated
})
export class Login {
  constructor(@Inject(Http) http) {
    console.log('http', http);
  }

  authenticate(username, password) {
    // this.http.get('/login');
  }
}

Я пытался:

export class Login {
  constructor(@Inject(Http) http) {
    console.log('http', http);
  }
}
/********************/
@Inject(Http)
export class Login {
  constructor(http) {
    console.log('http', http);
  }
}
/********************/
export class Login {
  constructor(Http: http) {
    console.log('http', http);
  }
}
/********************/
export class Login {
  constructor(http = Http) {
    console.log('http', http);
  }
}
/********************/
export class Login {
  constructor(Http) {
    this.http = new Http()
    console.log('http', this.http);
  }
}
/********************/
export class Login {
  constructor(http = new Http()) {
    console.log('http', http);
  }
}

Все кроме первой компиляции. Другие дают мне доступ либо к классу Http, либо к экземпляру http. Но никто не работает.

Я попытался проследить за обсуждением, на которое ссылается Эрик Мартинес в своем комментарии. Login.js сейчас:

import {Component, Inject, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2';
import {HTTP_BINDINGS, Http, BaseRequestOptions, RequestOptions, RequestMethods} from 'angular2/http';

@Component({
  selector: 'login'
})
@View({
  templateUrl: './components/login/login.html',
  styleUrls: ['components/login/login.css'],
  directives: [CORE_DIRECTIVES],
  encapsulation: ViewEncapsulation.Emulated,
  bindings: [Http]
})
export class Login {

  constructor(http) {
    this.http = http;
    console.log('http', http);
  }

  authenticate(usernameEl, passwordEl) {
    var username = usernameEl.value;
    var password = passwordEl.value;
    console.log('username', username, password);

    // this.http.get('/login');
  }
}

Login.parameters = [Http];

Он компилируется сейчас, но генерирует следующую ошибку:

Uncaught (в обещании) NoBindingError {сообщение: "Нет поставщика для Http! (Логин -> Http)", стек: "Ошибка: исключение DI" в NoBindingError.BaseExce… or._new ( http://localhost:3000/bundle.js:7319:22) ", keys: Array [2], инжекторы: Array[2]}constructResolvingMessage: (keys) аргументы: (...) вызывающая сторона: (...) длина: 1name: ""prototype: Object__proto__: ()context: (...) инжекторы: Array[2]0: Injector1: Injectorlength: 2__proto__: Array[0]keys: Array[2] сообщение: "Нет поставщика для стека Http! (Login -> Http)": "Ошибка: исключение DI" в NoBindingError.BaseException [как конструктор] ( http://localhost:3000/bundle.js:8400:24) ↵ в NoBindingError.AbstractBindingError [как конструктор] ( http://localhost:3000/bundle.js:9066:17) ↵ в новой ошибке NoBindingError ( http://localhost:3000/bundle.js:9102:17) ↵ в Injector._throwOrNull ( http://localhost:3000/bundle.js:7469:20) ↵ в Injector._getByKeyDefault ( http://localhost:3000/bundle.js:7516:22) ↵
в Injector._getByKey ( http://localhost:3000/bundle.js:7461:26) ↵ в Injector._getByDependency ( http://localhost:3000/bundle.js:7447:26) ↵
в Injector._instantiate ( http://localhost:3000/bundle.js:7339:37) ↵
в Injector._instantiateBinding ( http://localhost:3000/bundle.js:7330:26) ↵ в Injector._new ( http://localhost:3000/bundle.js:7319:22) "proto: __

4 ответа

Решение

Так как у вас есть @Decorators включен в Вавилоне

... Я уточню этот ответ для работы с вашими настройками.

1. Вам не хватает HTTP_PROVIDERS

Константа HTTP_PROVIDERS включает ряд функций, необходимых для обработки HTTP-запросов / ответов.

import {Http, HTTP_PROVIDERS} from 'angular2/http';    

@Component({
  selector: 'login',
  providers: [ HTTP_PROVIDERS ]
})

2. Вам нужно отключить синтаксис DI (Dependency Injection)

Как уже упоминалось в ответе @alexpods.

Убрать статическую типизацию

constructor(http) {

@Inject обрабатывает DI неявно, но поддерживается только в Angular2+Typescript. Поскольку вы используете Angular2+ES6, вам нужно присоединить статический параметр getter к вашему классу, чтобы обеспечить специфичный для ES6 эквивалент.

static get parameters() {
    return [[Http]];
}

3. Вам нужно привязать экземпляр Http к вашему классу в конструкторе

Сделав это, он станет доступным в вашем authenticate() метод.

constructor(http) {
    this.http = http;
    console.log('http', this.http);
}

... и полная реализация:

import {Component, Inject, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2';
import {Http, HTTP_PROVIDERS} from 'angular2/http';

@Component({
  selector: 'login',
  // required for Http
  providers: [ HTTP_PROVIDERS ]
})
@View({
  templateUrl: './components/login/login.html',
  styleUrls: ['components/login/login.css'],
  directives: [CORE_DIRECTIVES],
  encapsulation: ViewEncapsulation.Emulated
})
export class Login {
  constructor(http) {
    // bind http to your class during construction
    //   so it's available to authenticate()
    this.http = http;
  }

  // Angular2 DI desugar'd
  static get parameters() {
    return [[Http]];
  }

  authenticate(username, password) {
    this.http.get('/login');
  }
}

В стороне: я точно знаю, что это работает, потому что я использую это для <ng2-markdown> компонент на EvanPlaice.com.

Как я уже ответил здесь, если вы пишете код в ES7, используйте статический геттер для parameters свойство указывать инъекции в constructor вашего компонента. Например:

import { Http } from 'angular2/http';
// other imports ...

// component decorators ...
export class Login {

  static get parameters() {
    return [[Http]];
  }

  constructor(http) {
    this.http = http;
    console.log('http', http);
  }

  // other methods
}

Я думаю, что это самый лаконичный метод на данный момент.

Помните, что в настоящее время нет предложений по поддержке декораторов параметров в ES7 (например, см. Эту проблему для Babel).

У меня работает метод из официального обзора API:

import {Http, HTTP_PROVIDERS} from 'angular2/http';
@Component({
  selector: 'http-app',
  viewProviders: [HTTP_PROVIDERS],
  templateUrl: 'people.html'
})
class PeopleComponent {
  constructor(http: Http) {
    http.get('people.json')
      .map(res => res.json())
      .subscribe(people => this.people = people);
  }
}

С помощью https://github.com/shuhei/babel-plugin-angular2-annotations вы можете внедрить сервисы с аннотациями типов параметров конструктора, как в TypeScript.

Установите плагины Babel:

npm install -D babel-plugin-angular2-annotations babel-plugin-transform-decorators-legacy babel-plugin-transform-class-properties babel-plugin-transform-flow-strip-types babel-preset-es2015

.babelrc:

{
  "plugins": [
    "angular2-annotations",
    "transform-decorators-legacy",
    "transform-class-properties",
    "transform-flow-strip-types"
  ],
  "presets": [
    "es2015"
  ]
}

и вуаля!

import {Component, View, CORE_DIRECTIVES, ViewEncapsulation} from 'angular2/angular2';
import {Http} from 'angular2/http';

@Component({
  selector: 'login'
})
@View({
  templateUrl: './components/login/login.html',
  styleUrls: ['components/login/login.css'],
  directives: [CORE_DIRECTIVES],
  encapsulation: ViewEncapsulation.Emulated
})
export class Login {
  constructor(http: Http) {
    console.log('http', http);
    this.http = http;
  }

  authenticate(username, password) {
    this.http.get('/login');
  }
}

Обратите внимание, что подпись типа используется только для подсказки для внедрения зависимости и не используется для проверки типа.

Другие вопросы по тегам