Сервисы с ES6 (AngularJS)

У меня проблемы с доступом к встроенным службам Angular, таким как $http, при создании службы с ES6.

Например, я создаю службу «ResultsFinder», которая будет выполнять вызов AJAX, а затем выполнять некоторые действия. Проблема в том, что у меня есть доступ к $http только в конструкторе (если я передаю его в качестве аргумента), но не в других методах (таких как getResults).

См. этот пример кода:

(() => {
  'use strict';

  class ResultsFinder {
    constructor($http) {}
    getResults() {
      return 'ResultsFinder';
    }
  }

  /**
   * @ngdoc service
   * @name itemManager.service:ResultsFinder
   *
   * @description
   *
   */
  angular
    .module('itemManager')
    .service('ResultsFinder', ResultsFinder);
}());

Внутри getResults у меня нет доступа к $http. Чтобы получить доступ, я должен сделать что-то, что мне кажется неправильным, например:

(() => {
  'use strict';

  class ResultsFinder {
    constructor($http) {
      this.$http = $http;
    }
    getResults() {
      // Here I have access to this.$http
      return 'ResultsFinder';
    }
  }

  /**
   * @ngdoc service
   * @name itemManager.service:ResultsFinder
   *
   * @description
   *
   */
  angular
    .module('itemManager')
    .service('ResultsFinder', ResultsFinder);
}());

Кто-нибудь может дать мне несколько советов о правильном способе справиться с этим?


person jeffarese    schedule 15.04.2015    source источник
comment
Вот как работает класс, вы должны определить свои свойства в конструкторе и получить к ним доступ в других методах. В этом нет ничего плохого.   -  person Pierrickouw    schedule 15.04.2015
comment
Тогда это правильный способ создания сервисов? Мне кажется странным обращаться к глобальным службам с помощью this.$service.   -  person jeffarese    schedule 15.04.2015
comment
Сервис не глобальный. Это член класса. В браузерах глобальные переменные являются свойствами window. window.$http.get("/") будет недействительным. С помощью TypeScript вы сможете аннотировать элемент как private.   -  person Martin    schedule 15.04.2015


Ответы (1)


Вам нужно использовать this.$http внутри вашего метода getResults.

(() => {
  'use strict';
      
class ResultsFinder {
	
    static $inject = ['$http'];   
    constructor($http) {
        this.$http = $http;
    }
		
    getResults() {
        return this.$http.get('/foo/bar/');
    }
}

  /**
   * @ngdoc service
   * @name itemManager.service:ResultsFinder
   *
   * @description
   *
   */
  angular
    .module('itemManager')
    .service('ResultsFinder', ResultsFinder);
}());

В качестве примечания я добавил к вашему классу статическую $inject "аннотацию". Это лучшая практика, если вы не используете что-то вроде ngAnnotate. Это также упрощает изменение реализации, изменяя только значения $inject.

Если вы разработчик ES5, может быть полезно подумать о том, как это будет выглядеть в ES5.

ResultsFinder.$inject = ['$http'];
var ResultsFinder = function($http) {
    this.$http = $http;
}

ResultsFinder.prototype.getResults = function() {
    return this.$http.get('/foo/bar/');
}

ПРИМЕЧАНИЕ

Поскольку вы используете ES6, вероятно, следует использовать модули ES6 для организации вашего кода.

Вы определяете и экспортируете свой угловой модуль в модуль ES6:

import {module} from 'angular';

export var itemManager = module('itemManager', []);

Затем импортируйте модуль Angular

import {itemManager} from '../itemManager';

class ResultsFinder {

    static $inject = ['$http'];   
    constructor($http) {
        this.$http = $http;
    }

    getResults() {
        return this.$http.get('/foo/bar/');
    }
}

itemManager.service('ResultFinder', ResultFinder);
person Martin    schedule 15.04.2015
comment
Когда ваш код uglified или minified, параметр функции $http будет заменен чем-то вроде: a. Angular не будет знать, какую службу внедрить в этот момент. Вот где появляется $inject. Обычно это проблема, которая проявляется только после того, как код отправлен в QA или PROD. - person Martin; 15.04.2015
comment
Вы должны использовать $http, а не http. - person Martin; 15.04.2015
comment
Да, в вашем контроллере вы бы хотели MyController.$inject = ['ResultsFinder'];. - person Martin; 15.04.2015
comment
Этот ответ не кажется мне хорошей практикой. Я согласен с тем, что ОП не решается использовать this.$http, потому что тогда это просто становится бесполезным вне службы. Тогда кто-то мог бы использовать ResultsFinder.$http - я согласен, это неправильно. Любые другие решения? - person Jordan Carroll; 28.01.2016
comment
Джордан. Вы сможете использовать ResultsFinder.$http только в том случае, если во время сборки вы НЕ заворачиваете свой модуль в IIFE. Это следует делать всегда. Или просто оберните класс в IIFE. Выполнение инкапсуляции в конструкторе даст вам производительность. - person Martin; 29.01.2016