Почему я не получаю поставщика услуг в Angular, когда я указал сервис в качестве поставщика в функциональном модуле - PullRequest
1 голос
/ 11 марта 2020

У меня проблема с тем, что мое приложение выдает ошибку: No Provider for Data Service.

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

Мое приложение построено на Angular 9 с управлением операторами Ngrx и взаимодействует с базой данных Firestore.

Я не работаю с простым провайдером, так как пытаюсь ie преобразовать сервис в ngrx / data, который действительно предназначен для работы с Rest API, не поддерживающим firebase.

Ошибка в браузере * NullInjectorError: R3InjectorError (ProductsModule) [ProductsResolver -> DataService -> DataService -> DataService -> DataService -> DataService]: NullInjectorError: Нет поставщика для DataService! *

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

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

import { DataService } from "../services/generic-data-service";
import { Product } from "@shared/models/product.model";

import {
    ChangeDetectionStrategy,
    Component,
    OnInit,
    ViewEncapsulation,
    Inject
} from "@angular/core";

import { Observable } from "rxjs";

@Component({
    selector: "fw-products",
    templateUrl: "./products-list.component.html",
    styleUrls: ["./products-list.component.scss"],
    encapsulation: ViewEncapsulation.None,
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ProductsListComponent implements OnInit {
    products$: Observable<any>;

    constructor(
        @Inject("ProductsService")
        private _dataService: DataService<Product>
    ) {}


    ngOnInit(): void {
        this._dataService.getMyEntities().subscribe(data => {
            this._dataService.clearCache();
            this._dataService.upsertManyInCache(data);
            this._dataService.entities$.subscribe(
                data => console.log(data)
            );
        });
    }

}

Служба данных

import { FirestoreService } from "@core/services/firestore.service";
import { Product } from "@shared/models/product.model";
import { BaseModel } from "@shared/models/entity-base.model";

import { Injectable } from "@angular/core";

import {
    EntityCollectionServiceBase,
    EntityCollectionServiceElementsFactory
} from "@ngrx/data";
import { Observable } from "rxjs";

Injectable();
export class DataService<
    T extends BaseModel
> extends EntityCollectionServiceBase<T> {
    x: string;

    constructor(
        cls: typeof Product,
        public firestoreService: FirestoreService,
        elementsFactory: EntityCollectionServiceElementsFactory
    ) {
        super(cls.entityName, elementsFactory);
        this.x = cls.firebasePath;
    }

    getMyEntities(): Observable<any[]> {
        return this.firestoreService.getAll(this.x);
    }

    createEntity(data: any): void {
        this.firestoreService.createDoc(`${this.x}/`, data);
    }

    updateEntity(data: any): void {
        this.firestoreService.updateDoc(`${this.x}/`, data);
    }

    deleteEntity(data: any): void {
        this.firestoreService.deleteDoc(`${this.x}/`, data);
    }
}

Продукты Resolver

import { Injectable } from "@angular/core";
import {
    Resolve,
    ActivatedRouteSnapshot,
    RouterStateSnapshot
} from "@angular/router";
import { Observable } from "rxjs";
import { map, tap, filter, first } from "rxjs/operators";
import { DataService } from './generic-data-service';
import { Product } from '@shared/models/product.model';

@Injectable()
export class ProductsResolver implements Resolve<boolean> {
    constructor(private _productsService: DataService<Product>) {}

    resolve(
        route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
    ): Observable<boolean> {
        return this._productsService.loaded$.pipe(
            tap(loaded => {
                if (!loaded) {
                    this._productsService.getAll();
                }
            }),
            filter(loaded => !!loaded),
            first()
        );
    }
}

1 Ответ

1 голос
/ 12 марта 2020

Проблема была в моем распознавателе, я вызывал неправильный метод .getAll (), который использует поведение по умолчанию (вызов http для / api). То, что я должен был использовать, - это метод GetMyEntities (), который переопределяется, чтобы сделать запрос к firestore для загрузки данных.

Мне также нужно было бы обновить Resolver до Inject ("ProductService") в его Конструктор.

Я не мог просто использовать {обеспеченный: root}, потому что я переопределяю поведение по умолчанию (http-вызов / api) @ ngrx / data, чтобы вместо этого вызывать Firestore (AngularFire).

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

Приведенное выше решение хорошо работает сейчас, поскольку оно использует @ ngrx / data с firestore и фактически удаляет весь стандартный код, обычно необходимый с @ngrx для записи действий, редукторов, селекторов и т. Д. c.

...