Как создается в Angular сервис регистрация в массиве провайдеров с помощью Injectable


Содержание материала:

Проблема с внедрением Angular Service: @Injectable не работает, но провайдеры работают

Я просмотрел через SO, но ничего не смог найти с моей, казалось бы, странной проблемой. Я начну с того, что скопирую часть своего кода, чтобы дать контекст:

Хорошо, теперь, когда это здесь, вот моя проблема: когда я пытаюсь использовать @Injectable, как у меня выше, с объявленным модулем, я получаю следующую ошибку в своем браузере, но нет ошибки компиляции TS (есть циркуляр Ссылка предупреждение, хотя):

DashboardContainerComponent.html: 2 Ошибка ОШИБКИ: StaticInjectorError (AppModule) [DashboardElementComponent -> ApiService]: StaticInjectorError (Платформа: ядро) [DashboardElementComponent -> ApiService]: поставщик NullInjectorError: Ошибка поставщика

Когда я изменяю его на использование @Injectable () и раскомментирую своих провайдеров, мне это нравится, и все в порядке. Мне просто интересно, почему это так? Из прочтения документации Angular для 6.1 это, кажется, соответствует тому, что нужно.

Для получения дополнительной информации все это находится внутри подмодуля, и сервис предназначен быть изолированным для этого модуля. На данный момент, я просто озадачен тем, что мне не хватает, и как один из немногих сотрудников JS в моем офисе, и единственный, кто использует Angular, у меня нет второго взгляда, чтобы помочь мне определить, что я » м отсутствует.

Любая помощь в этом очень ценится, так как это жрет меня уже несколько дней. Заранее спасибо,

Изменить: Еще одна вещь, чтобы отметить, это было приложение, которое было обновлено с 5 до 6. Я следовал руководству и получил все это работает, так что, возможно, это источники от обновления?

Так что после дальнейшего изучения этой проблемы и функциональности я обнаружил, что я не единственный, кто сталкивается с этой проблемой, и, похоже, это происходит из-за неправильного понимания документации. Как упомянуто здесь: GitHub Angular CLI Issue 10170, как я и говорил, неверен, хотя документация по этой функции, похоже, говорит об обратном.

По сути, это создает цикл импорта, и TS делает свою работу по предотвращению такой проблемы. В настоящее время рекомендуемый способ использования @Injectable() — с помощью функции < providedIn: 'root' >который делает доступным сервис для инъекций на корневом уровне приложения. При этом, как представляется, он связывается только на верхнем уровне, если он используется в нескольких модулях или в корневом модуле. Если сервис используется только в одном субмодуле, он связан с этим субмодулем.

Мое решение было изменить на

для моих новых услуг, а остальные я оставил как в массиве providers определения модулей их соответствующих модулей. По крайней мере, до тех пор, пока providers больше не будут поддерживаться, все это будет хорошо работать вместе, тогда я переведу их всех в этот новый формат.

Angular: Провайдер объекта Window

Куда делась моя ссылка $window? Нет проблем, используйте этот провайдер для внедрения window в ваш Angular компонент.

Почему?

Потому что мы не хотим ссылаться на глобальный объект Window прямо в компоненте Angular, так как наше приложение может быть использовано в Angular Universal, и считается лучшей практикой избегать прямой ссылки на глобальные объекты. Пока вы возможно не планируете использовать Angular Universal, это позволяет нам прямо внедрить родной объект браузера Window в компонент.

Чем это отличается?

В то время как существует уже множество решений, которые предлагают методы косвенного доступа к объекту Window, я обнаружил, что многие из них в действительности не выполняют какого-либо условия проверки, которое приложение выполняет в контексте браузера, где у нас будет объект Window.

Вот пример решения, который мне показался неподходящим:

Беглый взгляд на него указывает на то, что проверка не осуществляется, если приложение выполняется в контексте браузера. Далее, мы возможно захотим поддерживать контекст для тестов, где нам может быть понадобится имитировать некоторые свойства или методы в объекте Window.

Предлагаемое решение

Ниже приводится решение создания расширяемого метода для внедрения Window в компоненты Angular. В моем приложении я поместил это в src/app/core/services/window.service.ts:

Несколько вещей, на которые стоит обратить внимание:

  • У меня есть InjectionToken объявленный как WINDOW , который экспортируется. Мы будем использовать это для внедрения объекта Window в наши компоненты.
  • Я определяю абстрактный класс WindowRef который имеет аксессор для свойства nativeWindow.
  • Затем, я определяю класс BrowserWindowRef расширяющий абстрактный класс, и реализовывающий свойство nativeWindow возвращать глобально доступный объект Window.
  • Функция windowFactory()определяет, выполняется ли приложение в контексте браузера, используя функцию isPlatformBrowser(). Сейчас, если приложение не выполняется в контексте браузера, я просто возвращаю новый Object. Эта часть расширяемая тем, что вы могли бы вернуть имитируемый объект в другой контекст. Функция ожидает экземпляр(инстанс) BrowserWindowRef и объект platformId. Эти зависимости определяются в windowProvider.
  • browserWindowProvider является (классом провайдера) ClassProvider который предоставляет экземпляр BrowserWindowRef используя injection token (токен внедрения) WindowRef.
  • windowProvider является (провайдером-фабрикой) FactoryProvider которая использует windowFactory чтобы возвращать объект Window (или пустой объект) когда используется injection token WINDOW.
  • И последнее, объявляем массив провайдеров с именем WINDOW_PROVIDERS.

Чтобы это использовать, необходимо добавить WINDOW_PROVIDERS в массив providers модуля декоратора app.module.ts:

У вас также может быть CoreModule (возможно с другим именем) – это модуль который содержит все сервисы, интерсепторы, модели и пр., доступные для приложения. В случае необходимости просто импортируйте WINDOW_PROVIDERS в этот модуль, который затем импортируется в AppModule.

После этого, мы можем использовать injection token WINDOW для внедрения window в компонент:

Как создается в Angular сервис: регистрация в массиве провайдеров с помощью Injectable

833 просмотра

3 ответа

3 Репутация автора

На этот вопрос уже есть ответ здесь:

Я действительно хочу знать, что такое провайдеры? какие отношения с DI в angular2?

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

Я не уверен, что экземпляр службы создан инжектором или провайдером? Если создан инжектор, зачем нам поставщики?

Ответы (3)

плюса

114 Репутация автора

Сервис не создан Инжектором. Когда вы создаете Сервис, вы используете аннотацию @Injectable только тогда, когда вы хотите добавить другой сервис в аннотированный сервис.

Каждый сервис должен быть в массиве провайдеров. Если вы объявите это в module.ts, у вас будет один и тот же экземпляр в каждом компоненте. Если вы объявите его в массиве поставщиков в Компоненте, этот экземпляр будет доступен только для этого Компонента и каждого его дочернего компонента.

Автор: cotnic Размещён: 21.07.2020 06:52

-2 плюса

752 Репутация автора

Просто для понимания.

1. Поставщики — это простые классы, которые должны быть одноразовыми.

2- Когда какой-либо поставщик (класс) внедряется во внедряемый компонент, он запрашивает у инжектора компонента предоставить внедренный экземпляр класса, посылая ключ этого класса

3- Если у инжектора есть тот единственный экземпляр против этого ключа, он возвращает экземпляр.

4- В противном случае он создает экземпляр и регистрирует этот экземпляр как синглтон

Топ-пост этого месяца:  Введение в язык JavaScript. Типы данных в JavaScript

Очень хорошим примером этого является Http-сервис, который внедряется в разные сервисы.

Автор: umar Размещён: 21.07.2020 06:55

1 плюс

370218 Репутация автора

Поставщик — это стратегия для DI по созданию экземпляров или получению значений, которые необходимо передать конструкторам или которые запрашиваются с помощью injector.get(..) .

(переданное значение provide: . является токеном для поиска поставщиков. Другой параметр — стратегия, используемая для создания экземпляра).

Когда DI создает экземпляр класса, он считывает параметры конструктора класса, который ему необходим для создания экземпляра или deps параметра поставщика, чтобы выяснить, какие значения необходимо передать этому конструктору для создания этого экземпляра.

Затем он ищет поставщиков, которые соответствуют этим обязательным значениям параметров (по типу параметра конструктора или токена, назначенного параметру конструктора с использованием @Inject(. ) декоратора).

Когда Angular нужен MyComponent экземпляр, он запрашивает его у DI, чтобы DI создал экземпляр, ему нужен экземпляр, MyService чтобы иметь возможность передать его конструктору. DI ищет поставщика MyService и создает экземпляр, или, если ранее он уже был создан, этот повторно используется.

Место регистрации провайдеров определяет, какой экземпляр или значение передается в конструктор.
В этом примере будет добавлен экземпляр поставщика компонентов.
Если у Компонента не будет providers: [MyService] строки, будет добавлен экземпляр от провайдера @NgModule() :

Каждый дочерний компонент имеет свой собственный инжектор, который является дочерним инжектором родительского компонента. Когда компонент создается, DI ищет поставщиков в инжекторе компонентов, затем в инжекторе родительского компонента, . тоже вверх AppComponent , а затем в @MgModule() инжекторах. Первый инжектор, у которого есть поставщик для требуемого токена, используется для получения экземпляра. Это означает, что имеет значение, где вы предоставляете поставщика. Если вы добавляете провайдера в компонент, вы получаете столько экземпляров предоставленной услуги, сколько есть экземпляров компонента. Если добавить поставщика только в @NgModule(. ) class AppModule<> то будет только один экземпляр в целом приложения.

Lazy-загруженные модули добавляют дополнительную сложность. Проверьте документы для более подробной информации.

Angular dependency injection

Provider (Поставщик)

Инжекторы и провайдеры могу конфигурироваться на трех уровнях приложения, путём задания метаданных в декораторах:

  1. @Injectable() — на уровне сервиса.
  2. @NgModule() — на уровен модуля NgModule.
  3. @Component() — на уровне компонента.

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

Провайдер класса

Провайдер переменной или константы

Зависмость от сущности, не являющейся классом. Вместо «прибитой» константы:

Тогда запись зависимости выглядит следующим образом:

Провайдер «фабрика»

Используется для случая получения сущности по условию.

Множественные провайдеры

Для случая, когда вместо одной зависимости требуется массив используется multi: true . При этом значение не перезаписывают массив, а добавляют в него значения.

Injector

Механизм разрешающий зависимости и создающий сущности

Инжектор — объект в системе Angular, который может найти зависимость по ключу в своем кеше или создать зависимость с использованием настроенного провайдера (Provider). Инжекторы создаются для NgModules автоматически как часть процесса начальной загрузки и наследуются через иерархию компонентов.

Работа с инжектором вручную.

Dependency

Обычно класс или константа. Тут всё просто — сущность, которую необходимо внедрить.

Зависимость Angular достаёт из декораторов @Component , @Pipe , @Directive , @Inject , @Injectable .

Как создать однопользовательский сервис в Angular 2? — angular

Я читал, что при инъекции, когда при начальной загрузке все дочерние пользователи используют один и тот же экземпляр, но мои основные и заголовочные компоненты (основное приложение включает компонент заголовка и роутер-выход), каждый получает отдельный экземпляр моих служб.

У меня есть служба FacebookService, которую я использую для звонков в javascript api facebook и UserService, который использует FacebookService. Вот мой бутстрап:

Из моего ведения журнала это выглядит как завершение вызова начальной загрузки, затем я вижу, что в FacebookService создается UserService до того, как код в каждом из конструкторов запускается, MainAppComponent, HeaderComponent и DefaultComponent:

    4 12
  • 12 окт 2020 2020-10-12 08:39:18
  • Jason Goemaat

12 ответов

В дополнение к вышеприведенным отличным ответам может быть что-то еще, что отсутствует, если вещи в вашем singleton все еще не ведут себя как одиночный. Я столкнулся с проблемой при вызове публичной функции на синглете и обнаружил, что использует неправильные переменные. Оказывается, проблема заключалась в том, что this не гарантируется привязкой к синглтону для любых публичных функций в singleton. Это можно исправить, следуя советам здесь, например:

Кроме того, вы можете просто объявить членов класса как public static вместо public , тогда контекст не имеет значения, но вам придется обращаться к ним, например SubscriptableService.onServiceRequested$ вместо использования инъекции зависимостей и доступа к ним через this.subscriptableService.onServiceRequested$ .

  • 12 окт 2020 2020-10-12 08:39:22

  • cjbarth

Если вы хотите сделать сервис singleton на уровне приложения, вы должны определить его в app.module.ts

провайдеров: [MyApplicationService] (вы можете определить то же самое в дочернем модуле, чтобы сделать его соответствующим модулем)

  • Не добавляйте эту службу в провайдер, который создает экземпляр для этого компонента, который нарушает концепцию singleton, просто вставляйте через конструктор.

Если вы хотите определить службу singleton на службе создания уровня компонента, добавьте эту услугу в app.module.ts и добавьте массив провайдеров внутри определенного компонента, как показано ниже в snipet.

Угловая 6 обеспечивает новый способ добавления услуги на уровне приложения. Вместо добавления класса сервиса в массив поставщиков [] в AppModule вы можете установить следующую конфигурацию в @Injectable():

@Injectable () класс экспорта MyService

«Новый синтаксис» предлагает одно преимущество: услуги могут быть загружены лениво по угловым (за кулисами), а избыточный код можно удалить автоматически. Это может привести к повышению производительности и скорости загрузки, хотя это действительно только для больших услуг и приложений в целом.

  • 12 окт 2020 2020-10-12 08:39:21
  • Vijay Barot

Просто объявляйте свой сервис как поставщика только в app.module.ts.

Это помогло мне.

то либо инициализируйте его, используя частный параметр конструктора:

или, если ваша служба используется из html, опция -prod будет требовать:

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

  • 12 окт 2020 2020-10-12 08:39:21
  • user1767316

это, кажется, хорошо работает для меня

  • 12 окт 2020 2020-10-12 08:39:21
  • Captain Harlock

Вы можете использовать useValue у поставщиков

  • 12 окт 2020 2020-10-12 08:39:21
  • Roman Rhrn Nesterov

Из Angular @6 вы можете providedIn Injectable .

Существует два способа сделать услугу одноэлементным в Angular:

  1. Объявите, что служба должна быть предоставлена в корне приложения.
  2. Включите службу в AppModule или в модуль, который импортируется только AppModule.

Начиная с Angular 6.0, предпочтительный способ создания однопользовательских сервисов — указать в сервисе, что он должен быть предоставлен в корне приложения. Это делается установкой enableIn для root в сервисе @Injectable decorator:

  • 12 окт 2020 2020-10-12 08:39:20
  • sabithpocker

Вот рабочий пример с Angular версия 2.3. Просто вызовите конструктор службы как способ создания этого объекта (private _userService: UserService). И он создаст синглтон для приложения.

user.service.ts

app.component.ts

  • 12 окт 2020 2020-10-12 08:39:20
  • David Dehghan

Добавление @Injectable decorator в Сервис, И, зарегистрировав его как поставщика в корневом модуле, сделает его одиночным.

  • 12 окт 2020 2020-10-12 08:39:20
  • bresleveloper

Синтаксис изменен. Проверьте ссылку

Зависимости — это одиночные числа в пределах объема инжектора. В приведенном ниже примере один экземпляр HeroService используется совместно с HeroesComponent и его дочерними элементами HeroListComponent.

Шаг 1. Создайте одноэлементный класс с @Injectable decorator

Шаг 2. Ввод в конструктор

Шаг 3. Зарегистрировать поставщика

  • 12 окт 2020 2020-10-12 08:39:20
  • Manish Jain

Я знаю, что angular имеет иерархические инжекторы, такие как Тьерри.

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

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

И затем на вашем компоненте вы используете свой собственный метод предоставления.

И вы должны иметь однопользовательскую службу, не зависимо от иерархических инжекторов.

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

  • 12 окт 2020 2020-10-12 08:39:20
  • Joel Almeida
Топ-пост этого месяца:  Google проводит испытание новой выдачи и предпочитает JSON-LD

Обновление (Угловое 6)

Изменен рекомендуемый способ создания службы singleton. В настоящее время рекомендуется указать в @Injectable decorator на службе, что он должен быть указан в «root». Это имеет для меня большой смысл, и нет необходимости перечислять все предоставляемые услуги в ваших модулях. Вы просто импортируете сервисы, когда они вам нужны, и они регистрируются в нужном месте. Вы также можете указать модуль, чтобы он предоставлялся только в том случае, если модуль импортирован.

Обновление (Угловое 2)

С NgModule, способ сделать это сейчас, я думаю, это создать «CoreModule» с вашим классом обслуживания в нем и перечислить службу в поставщиках модулей. Затем вы импортируете основной модуль в свой основной модуль приложения, который предоставит один экземпляр всем дочерним элементам, запрашивающим этот класс в своих конструкторах:

CoreModule.ts

AppModule.ts

Оригинальный ответ

Если вы перечислите поставщика в bootstrap() , вам не нужно указывать их в своем декораторе компонентов:

Фактически, перечисление вашего класса в «поставщиках» создает новый экземпляр, если какой-либо родительский компонент уже перечисляет его, тогда детям это не нужно, и если они это сделают, они получат новый экземпляр.

  • 12 окт 2020 2020-10-12 08:39:19
  • Jason Goemaat

Джейсон совершенно прав! Это вызвано тем, как работает инъекция зависимостей. Он основан на иерархических инжекторах.

В приложении Angular2 есть несколько инжекторов:

  • Корневой, который вы настраиваете при загрузке приложения
  • Инжектор на компонент. Если вы используете компонент внутри другого. Инжектор компонентов — это дочерний компонент родительского компонента. Компонент приложения (тот, который вы указываете при расширении вашего приложения) имеет корневой инжектор в качестве родительского).

Когда Angular2 пытается вставить что-то в конструктор компонента:

  • Он смотрит на инжектор, связанный с компонентом. Если есть соответствующий, он будет использовать его для получения соответствующего экземпляра. Этот экземпляр лениво создан и является одиночным для этого инжектора.
  • Если на этом уровне нет провайдера, он будет смотреть на родительский инжектор (и т.д.).

Итак, если вы хотите иметь одноэлемент для всего приложения, вам необходимо определить провайдера либо на уровне инжектора корня, либо в инжекторе приложения.


Но Angular2 будет смотреть на дерево инжектора снизу. Это означает, что провайдер на самом низком уровне будет использоваться, и объем связанного экземпляра будет таким уровнем.

См. этот вопрос для получения дополнительной информации:

Angular 2 Http Service Injectable

I’m pulling a big object from my server using Angular 2 service when the website starts. The data I need to pull looks like this:

And I set up the service this way:

And in my component, I inject the service so that I can get data:

However, in the AllDataService, the error message tells me that properties (Exp, Edu, Skills. ) don’t exist in Response. How should I setup my http service correctly so that I can pull the data I want at start and make sure all the components get the data? Thanks

Как правильно передавать данные через сервис Angular?

Делаю первые шаги в Angular 7, перехожу с Vue и сложновато как-то пока понимать как тут все делается.
Есть два компонента — search и result. В search я ввожу данные для поиска(string), а в result хочу получить эти данные. Помогите как это сделать?
Корневой компонент

ну и если нужен шаблон search

  • Вопрос задан 30 мар.
  • 396 просмотров

Для вашего случая существует лучшая практика: так называемые умные и глупые компоненты: https://medium.com/@dan_abramov/smart-and-dumb-com. (это оригинальная статья от автора реакта, но в ангуляре принципы такие же)

В нашем случае компоненты search и result — глупые компоненты, которые только и делают, что возвращают строку ввода (search) и отображают данные (result). Так же у нас имеется умный компонент searchResults, который знает как отреагировать на данные из search и правильно отобразить result.

Search и Result ничего не должны знать об HttpService. Он в них не инжектится.

Использование сервисов для передачи данных между компонентами в ангуляре — это самые распространённые грабли во фреймворке. Причём эти грабли настолько хитрые, что большинство программистов даже не понимает что ходит по ним. Самый верный способ не наступать на грабли — это забыть навсегда про private и public переменные в сервисах (другими словами сервис не должен иметь состояние). Без этого можно жить и причём легко и спокойно если начать использовать NxRx для хранения состояния системы.

danilr, я только что подправил код слегка (заменил onSearch на onQuery).

Попробуйте сделать компоненты Search и Result независимыми от сервиса: компонент search должен возвращать строку ввода (н и принимать исходное значение, естественно). А компонент result должен принимать массив результатов и правильно рендерить его. Будет значительно больше шансов что эти компоненты будут переиспользованы где-то еще.

Должен вас огорчить, но в ангуляре (как и во многих других фреймворках и языках программирования) не существует неуродского способа связывать компоненты через сервисы. Нормальный способ — это NgRx, но он требует понимания редакса и rxjs.

Если вам уж совсем не сидится без сервиса, то делайте как-то так:

И там где вы рендерите компоненты:

В принципе, вы можете заинжектить filmsDataService непосредственно, в search и result. Но это затруднит их дальнейшее переиспользование.

Провайдеры Angular

Провайдеры — классы, создающие объекты тогда, когда Angular впервые сталкивается с потребностью разрешить зависимость.

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

Обычно провайдеры определяются в свойстве providers декоратора @NgModule (также их можно определять в компонентах и директивах).

Провайдеры

Angular предоставляет разных провайдеров, которые создают объекты разными способами, таким образом мы можем управлять процессом создания служб.

  • Провайдер класса — настраивается при помощи класса, зависимости разрешаются от экземпляра класса.
  • Провайдер значения — настраивается при помощи объекта, зависимости разрешаются от объекта.
  • Провайдер фабрики — настраивается при помощи функции, зависимости разрешаются от объекта, который создается вызовом функции.
  • Провайдер существующий службы — настраивается при помощи имени другой службы, позволяет создавать псевдонимы служб.

Провайдер класса

Свойства провайдера класса:

  • provide — маркер/token
  • useClass — класс от которого создается экземпляр для разрешения зависимостей

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

Декоратор @Inject определяет маркер провайдера для разрешения зависимостей.

Класс InjectionToken

Класс OpaqueToken deprecated. Вместо класса OpaqueToken используется InjectionToken — используется для создания уникальных маркеров.

«logger» — это строковое значение, которое идентифицирует службу, но маркером становится экземпляр InjectionToken .

Регистрируем в модуле:

Объявляем зависимость при помощи InjectionToken :

Провайдер значения

Провайдер значения на angular.io

Провайдер значения используется в том случае, когда вам нужно взять ответственность за создание объектов служб на себя (для настройки его конфигурации используется объект, а не тип/класс). Также используется, когда службы являются простыми типами.

Провайдер фабрики

Провайдер фабрики использует функцию для создания объекта, который в свою очередь используется для разрешения зависимостей.

Свойства провайдера фабрики

  • provide — задает маркер службы
  • deps — задает массив маркеров провайдеров, котороые будут разрешены и переданы функции, определенной в свойстве useFactory. Свойство deps позволяет создавать зависимости от других служб.
  • useFactory — задает функцию, которая определяет объект службы. Объекты, полученные в результате разрешения маркеров свойства deps, будут переданы в функцию как аргументы. Результат функции и есть объект, который используется для разрешения зависимостей.

Инжекторы и как они разрешаются

Создавая новый экземпляр класса Angular разрешает зависимости при помощи инжекторов. Существует иерархия инжекторов соответствующая дереву компонентов и директив в приложении. У каждого компонента и директивы свой собственный инжектор. Для каждого инжектора можно настроить свой собственный набор провайдеров — это так называемые локальные провайдеры. Зависимости в Angular разрешаются путем использования ближайшего инжектора компонента или директивы.

Таким образом мы можем установить локального провайдера для директивы ( selector: «div» ) и этот провайдер будет разрешен в соответствующем pipe (у дочернего элемента по отношению к div ), у которого используется соответствующая зависимость.

Топ-пост этого месяца:  Окно просмотра в мобильном браузере использование единиц измерения

Favicon

Блог по web технологиям. Веб студия г. Воронеж. Создание и поддержка сайтов на заказ.

  • Главная
  • /
  • JavaScript
  • /
  • Фронтенд
  • /
  • Как создать полностраничный веб-сайт в Angular. Часть 2 (4)

Как создать полностраничный веб-сайт в Angular. Часть 2 (4)

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

Как создать полностраничный веб-сайт в Angular. Часть 2 (4)

05. Генерируем content service

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

Как и с нашим page component, мы можем использовать CLI для создания нашей контент службы. Мы создадим каталог shared , затем подкаталог services , а затем с помощью ng g создадим наш сервис.

Как создать однопользовательский сервис в Angular 2? — angular

Я читал, что при инъекции, когда при начальной загрузке все дочерние пользователи используют один и тот же экземпляр, но мои основные и заголовочные компоненты (основное приложение включает компонент заголовка и роутер-выход), каждый получает отдельный экземпляр моих служб.

У меня есть служба FacebookService, которую я использую для звонков в javascript api facebook и UserService, который использует FacebookService. Вот мой бутстрап:

Из моего ведения журнала это выглядит как завершение вызова начальной загрузки, затем я вижу, что в FacebookService создается UserService до того, как код в каждом из конструкторов запускается, MainAppComponent, HeaderComponent и DefaultComponent:

    5 12
  • 12 окт 2020 2020-10-12 08:39:18
  • Jason Goemaat

12 ответов

В дополнение к вышеприведенным отличным ответам может быть что-то еще, что отсутствует, если вещи в вашем singleton все еще не ведут себя как одиночный. Я столкнулся с проблемой при вызове публичной функции на синглете и обнаружил, что использует неправильные переменные. Оказывается, проблема заключалась в том, что this не гарантируется привязкой к синглтону для любых публичных функций в singleton. Это можно исправить, следуя советам здесь, например:

Кроме того, вы можете просто объявить членов класса как public static вместо public , тогда контекст не имеет значения, но вам придется обращаться к ним, например SubscriptableService.onServiceRequested$ вместо использования инъекции зависимостей и доступа к ним через this.subscriptableService.onServiceRequested$ .

  • 12 окт 2020 2020-10-12 08:39:22
  • cjbarth

Если вы хотите сделать сервис singleton на уровне приложения, вы должны определить его в app.module.ts

провайдеров: [MyApplicationService] (вы можете определить то же самое в дочернем модуле, чтобы сделать его соответствующим модулем)

  • Не добавляйте эту службу в провайдер, который создает экземпляр для этого компонента, который нарушает концепцию singleton, просто вставляйте через конструктор.

Если вы хотите определить службу singleton на службе создания уровня компонента, добавьте эту услугу в app.module.ts и добавьте массив провайдеров внутри определенного компонента, как показано ниже в snipet.

Угловая 6 обеспечивает новый способ добавления услуги на уровне приложения. Вместо добавления класса сервиса в массив поставщиков [] в AppModule вы можете установить следующую конфигурацию в @Injectable():

@Injectable () класс экспорта MyService

«Новый синтаксис» предлагает одно преимущество: услуги могут быть загружены лениво по угловым (за кулисами), а избыточный код можно удалить автоматически. Это может привести к повышению производительности и скорости загрузки, хотя это действительно только для больших услуг и приложений в целом.

  • 12 окт 2020 2020-10-12 08:39:21
  • Vijay Barot

Просто объявляйте свой сервис как поставщика только в app.module.ts.

Это помогло мне.

то либо инициализируйте его, используя частный параметр конструктора:

или, если ваша служба используется из html, опция -prod будет требовать:

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

  • 12 окт 2020 2020-10-12 08:39:21
  • user1767316

это, кажется, хорошо работает для меня

  • 12 окт 2020 2020-10-12 08:39:21
  • Captain Harlock

Вы можете использовать useValue у поставщиков

  • 12 окт 2020 2020-10-12 08:39:21
  • Roman Rhrn Nesterov

Из Angular @6 вы можете providedIn Injectable .

Существует два способа сделать услугу одноэлементным в Angular:

  1. Объявите, что служба должна быть предоставлена в корне приложения.
  2. Включите службу в AppModule или в модуль, который импортируется только AppModule.

Начиная с Angular 6.0, предпочтительный способ создания однопользовательских сервисов — указать в сервисе, что он должен быть предоставлен в корне приложения. Это делается установкой enableIn для root в сервисе @Injectable decorator:

  • 12 окт 2020 2020-10-12 08:39:20
  • sabithpocker

Вот рабочий пример с Angular версия 2.3. Просто вызовите конструктор службы как способ создания этого объекта (private _userService: UserService). И он создаст синглтон для приложения.

user.service.ts

app.component.ts

  • 12 окт 2020 2020-10-12 08:39:20
  • David Dehghan

Добавление @Injectable decorator в Сервис, И, зарегистрировав его как поставщика в корневом модуле, сделает его одиночным.

  • 12 окт 2020 2020-10-12 08:39:20
  • bresleveloper

Синтаксис изменен. Проверьте ссылку

Зависимости — это одиночные числа в пределах объема инжектора. В приведенном ниже примере один экземпляр HeroService используется совместно с HeroesComponent и его дочерними элементами HeroListComponent.

Шаг 1. Создайте одноэлементный класс с @Injectable decorator

Шаг 2. Ввод в конструктор

Шаг 3. Зарегистрировать поставщика

  • 12 окт 2020 2020-10-12 08:39:20
  • Manish Jain

Я знаю, что angular имеет иерархические инжекторы, такие как Тьерри.

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

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

И затем на вашем компоненте вы используете свой собственный метод предоставления.

И вы должны иметь однопользовательскую службу, не зависимо от иерархических инжекторов.

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

  • 12 окт 2020 2020-10-12 08:39:20
  • Joel Almeida

Обновление (Угловое 6)

Изменен рекомендуемый способ создания службы singleton. В настоящее время рекомендуется указать в @Injectable decorator на службе, что он должен быть указан в «root». Это имеет для меня большой смысл, и нет необходимости перечислять все предоставляемые услуги в ваших модулях. Вы просто импортируете сервисы, когда они вам нужны, и они регистрируются в нужном месте. Вы также можете указать модуль, чтобы он предоставлялся только в том случае, если модуль импортирован.

Обновление (Угловое 2)

С NgModule, способ сделать это сейчас, я думаю, это создать «CoreModule» с вашим классом обслуживания в нем и перечислить службу в поставщиках модулей. Затем вы импортируете основной модуль в свой основной модуль приложения, который предоставит один экземпляр всем дочерним элементам, запрашивающим этот класс в своих конструкторах:

CoreModule.ts

AppModule.ts

Оригинальный ответ

Если вы перечислите поставщика в bootstrap() , вам не нужно указывать их в своем декораторе компонентов:

Фактически, перечисление вашего класса в «поставщиках» создает новый экземпляр, если какой-либо родительский компонент уже перечисляет его, тогда детям это не нужно, и если они это сделают, они получат новый экземпляр.

  • 12 окт 2020 2020-10-12 08:39:19
  • Jason Goemaat

Джейсон совершенно прав! Это вызвано тем, как работает инъекция зависимостей. Он основан на иерархических инжекторах.

В приложении Angular2 есть несколько инжекторов:

  • Корневой, который вы настраиваете при загрузке приложения
  • Инжектор на компонент. Если вы используете компонент внутри другого. Инжектор компонентов — это дочерний компонент родительского компонента. Компонент приложения (тот, который вы указываете при расширении вашего приложения) имеет корневой инжектор в качестве родительского).

Когда Angular2 пытается вставить что-то в конструктор компонента:

  • Он смотрит на инжектор, связанный с компонентом. Если есть соответствующий, он будет использовать его для получения соответствующего экземпляра. Этот экземпляр лениво создан и является одиночным для этого инжектора.
  • Если на этом уровне нет провайдера, он будет смотреть на родительский инжектор (и т.д.).

Итак, если вы хотите иметь одноэлемент для всего приложения, вам необходимо определить провайдера либо на уровне инжектора корня, либо в инжекторе приложения.

Но Angular2 будет смотреть на дерево инжектора снизу. Это означает, что провайдер на самом низком уровне будет использоваться, и объем связанного экземпляра будет таким уровнем.

См. этот вопрос для получения дополнительной информации:

Добавить комментарий