Используйте $http внутри настраиваемого поставщика в app config, angular.js

Основной вопрос - возможно ли это? Я пробовал без везения.

main app.js

...
var app = angular.module('myApp', ['services']);
app.config(['customProvider', function (customProvider) {

}]);
...

сам поставщик

var services = angular.module('services', []);
services.provider('custom', function ($http) {
});

И у меня такая ошибка:

Uncaught Error: Unknown provider: $http from services 

Любые идеи?

Спасибо!

Ответ 1

В нижней строке:

  • Вы не можете вводить услугу в раздел конфигурации поставщика.
  • Вы можете ввести службу в раздел, который инициализирует службу поставщика.

Детали:

Структура

Angular имеет 2-фазный процесс инициализации:

ФАЗА 1: Конфигурация

Во время фазы config все провайдеры инициализируются, и все секции config выполняются. Секции config могут содержать код, который настраивает объекты-провайдеры, и поэтому им могут быть введены объекты-поставщики. Однако, поскольку поставщики - это фабрики для объектов службы, и на этом этапе провайдеры не полностью инициализированы/настроены → , вы не можете попросить провайдера создать для вас сервис на этом этапе → на этапе конфигурации, который вы не могут использовать/внедрять службы. Когда эта фаза завершена, все поставщики готовы (после завершения фазы конфигурации конфигурация конфигурации не может быть выполнена).

ФАЗА 2: Выполнить

В фазе run выполняются все секции run. На этом этапе провайдеры готовы и могут создавать сервисы → во время фазы run вы можете использовать/внедрять службы.

Примеры:

1. Включение службы $http в функцию инициализации провайдера НЕ РАБОТАЕТ

//ERRONEOUS
angular.module('myModule').provider('myProvider', function($http) {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function() {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

Так как мы пытаемся внедрить службу $http в функцию, которая выполняется во время фазы config, мы получим ошибку:

Uncaught Error: Unknown provider: $http from services 

Эта ошибка на самом деле говорит о том, что $httpProvider, который используется для создания службы $http еще не готов (поскольку мы все еще находимся в фазе config).

2. Включение службы $http в функцию инициализации службы WILL:

//OK
angular.module('myModule').provider('myProvider', function() {
    // SECTION 1: code to initialize/configure the PROVIDER goes here (executed during `config` phase)
    ...

    this.$get = function($http) {
        // code to initialize/configure the SERVICE goes here (executed during `run` stage)

        return myService;
    };
});

Поскольку мы теперь вводим службу в функцию инициализации службы, которая выполняется во время фазы run, этот код будет работать.

Ответ 2

Это может дать вам небольшое преимущество:

var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');

Но будьте осторожны, обратные вызовы с успехом/ошибкой могут привести вас в состояние гонки между началом приложения и ответом сервера.

Ответ 3

Это старый вопрос, кажется, что у нас есть яйцо с куриным яйцом, если мы хотим полагаться на основные возможности библиотеки.

Вместо того, чтобы решить проблему фундаментальным образом, я сделал обход. Создайте директиву, которая обертывает все тело. Ex.

<body ng-app="app">
  <div mc-body>
    Hello World
  </div>
</body>

Теперь mc-body необходимо инициализировать до рендеринга (один раз), например.

link: function(scope, element, attrs) {
  Auth.login().then() ...
}

Auth - это служба или поставщик, например

.provider('Auth', function() {
  ... keep your auth configurations
  return {
    $get: function($http) {
      return {
        login: function() {
          ... do something about the http
        }
      }
    }
  }
})

Мне кажется, что у меня есть контроль над порядком загрузки, это происходит после того, как обычный загрузочный блок разрешит всю конфигурацию провайдера, а затем попытается инициализировать директиву mc-body.

И эта директива, как мне кажется, может опережать маршрутизацию, поскольку маршрутизация также вводится через директиву ex. <ui-route />. Но я могу ошибаться в этом. Требуется еще несколько исследований.

Ответ 4

В ответ на ваш вопрос "Любые идеи?", я бы ответил "да". Но подождите, там еще!

Я предлагаю просто использовать JQuery в конфиге. Например:

var app = angular.module('myApp', ['services']);
app.config(['$anyProvider', function ($anyProvider) {
    $.ajax({
        url: 'www.something.com/api/lolol',
        success: function (result) {
            $anyProvider.doSomething(result);
        }
    });
}]);