Pull to refresh

В чем разница между factory и provider в AngularJS (на пальцах)

Website development *JavaScript *Angular *
Tutorial
Как-то давно переводил статью «Понимание типов сервисов в AngularJS (constant, value, factory, service, provider)». На практике, конечно, не всё пригождается, поэтому в рамках понижения порога вхождения в Ангуляр, объясню проще.

Никаких фабрик в Ангуляре нет. Есть только провайдеры. Записываются так:

app.provider('$helloWorld', function() {
  return {
    world: 'World',
    $get: function($hello) {
      return $hello + this.world;
    }
  }
});


После этого Ангуляр создаст сервис из метода $get:

$helloWorld = function($hello) {
  return $hello + this.world;
}


и его провайдер для настройки остальных параметров:

$helloWorldProvider = {
  world: 'World'
}


Провайдер мы используем для настройки сервиса (на стадии конфигурации):

app.config(function($helloWorldProvider) {
  $helloWorldProvider.world = 'Piter';
})


Сам сервис — после запуска приложения:

app.controller('MainCtrl', function($scope, $helloWorld) {
  $scope.title = $helloWorld; // $hello + 'Piter'
});


Предположим, что настройки нам не нужны:

app.provider('$helloWorld', function() {
  return {
    $get: function($hello) {
      return $hello + 'World';
    }
  }
});


То, что мы сейчас записали есть ни что иное как фабрика. То же самое можно записать так:

app.factory('$helloWorld', function($hello) {
  return $hello + 'World';
});


Разумеется, и в этом случае Ангуляр создаст $helloWorldProvider, только он будет без параметров — пустым.

Вывод: factory, service, value, constant — всего лишь синтаксический сахар для provider

P.S. $hello это просто какой-то наш сервис, взятый для примера:

app.factory('$hello', function() {
  return 'Hello';
});


P.P.S Шпаргалка

Provider
app.provider('$helloWorld', function() {
  return {
    world: 'World',
    $get: function($hello) {
      return $hello + this.world;
    }
  }
});


Factory
app.factory('$helloWorld', function($hello) {
  return $hello + 'World';
});

// или

app.provider('$helloWorld', function() {
  return {
    $get: function($hello) {
      return $hello + 'World';
    }
  }
});


Service
app.service('$helloWorld', HelloWorldClass);

// или

app.provider('$helloWorld', function() {
  return {
    $get: function($hello) {
      return new HelloWorldClass($hello);
    }
  }
});


Value
app.value('$helloWorld', {greating: 'Hello'});

// или

app.provider('$helloWorld', function() {
  return {
    $get: function() {
      return {greating: 'Hello'};
    }
  }
});


Constant
app.constant('$helloWorld', {world: 'Piter'});

// или

app.provider('$helloWorld', function() {
  return {
    world: 'Piter',
    $get: function() {
        return this; //без $get
    }
  }
});

// В config вызывается без суффикса Provider
app.config(function($helloWorld) { ... })


P.P.P.S
function HelloWorldClass($hello) {
  ...
}

app.service('$helloWorld', HelloWorldClass);

Как Ангуляр узнает, какие параметры передать в конструктор? Дело в том, что HelloWorldClass (да и любая функция в $get) запускается через $injector.invoke(fn), а это такая штука, которая читает код функции, вытаскивает аргументы из скобочек и подтягивает одноименные сервисы ($hello в нашем случае). Всё просто!
Tags:
Hubs:
Total votes 45: ↑36 and ↓9 +27
Views 52K
Comments Comments 9