firebase 零进样器错误:没有用于InjectionToken的提供程序angularfire2.app.options! 2021

xmakbtuz  于 2023-03-09  发布在  Angular
关注(0)|答案(8)|浏览(136)

好吧,我刚开始使用Angular 型的firebase,我已经挠头两天了。大多数的教程都是针对旧版本的firebase
这是我在将身份验证服务注入组件时收到的错误

Uncaught (in promise): NullInjectorError: R3InjectorError(AppModule)[LoginService -> AngularFireAuth -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]: 
  NullInjectorError: No provider for InjectionToken angularfire2.app.options!
NullInjectorError: R3InjectorError(AppModule)[LoginService -> AngularFireAuth -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options -> InjectionToken angularfire2.app.options]: 
  NullInjectorError: No provider for InjectionToken angularfire2.app.options!

以下链接到目前为止没有帮助
Link1Link2Link3

    • 应用程序模块. ts**
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

import { LoginService } from 'src/services/login.service';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { LoginComponent } from './components/login/login.component';
import { HomeComponent } from './components/home/home.component';
import { NotFoundComponent } from './components/not-found/not-found.component';

import { environment } from '../environments/environment';

import { initializeApp,provideFirebaseApp } from '@angular/fire/app';
import { provideAuth,getAuth } from '@angular/fire/auth';
import { provideDatabase,getDatabase } from '@angular/fire/database';
import { provideFirestore,getFirestore } from '@angular/fire/firestore';
import { AngularFirestore } from '@angular/fire/compat/firestore';

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    HomeComponent,
    NotFoundComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideAuth(() => getAuth()),
    provideDatabase(() => getDatabase()),
    provideFirestore(() => getFirestore()),
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [LoginService],
  bootstrap: [AppComponent]
})
export class AppModule { }
    • 登录服务ts**
import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { Router } from '@angular/router';
import { AngularFirestore } from '@angular/fire/compat/firestore';

@Injectable({
  providedIn: 'root'
})
export class LoginService {
  userLoggedIn: boolean;  

  constructor(private afAuth: AngularFireAuth, private router : Router,  private afs: AngularFirestore) {
    this.userLoggedIn = false;
  }

  loginUser(email: string, password: string): Promise<any> {
      return this.afAuth.signInWithEmailAndPassword(email,password)
        .then(() => {
            console.log('Auth Service: loginUser: success');
             this.router.navigate(['']);
        })
        .catch(error => {
            console.log('Auth Service: login error...');
            console.log('error code', error.code);
            console.log('error', error);
            if (error.code)
                return { isValid: false, message: error.message };
            else
                return { isValid: false, message : "Login Error"}
        });
  }

}
    • 登录.组件. ts**
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { LoginService } from 'src/services/login.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {
  loginFormCtrl: FormGroup;

  constructor(private LoginService: LoginService, private router: Router) {
    this.loginFormCtrl = new FormGroup({
      email: new FormControl('', Validators.required),
      password: new FormControl(null, Validators.required)
    })
  }

  ngOnInit(): void {

  }

  onLogin() {
    if (this.loginFormCtrl.invalid)
      return;

    this.LoginService.loginUser(this.loginFormCtrl.value.email, this.loginFormCtrl.value.password).then((result) => {
      
      if (result == null) {                              
        console.log('logging in...');
        this.router.navigate(['']);             
      }
      else if (result.isValid == false) {
        console.log('login error', result);
      }
    });
  }

}
    • 包. json**
{
  "name": "fire-base",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~12.2.0",
    "@angular/common": "~12.2.0",
    "@angular/compiler": "~12.2.0",
    "@angular/core": "~12.2.0",
    "@angular/fire": "^7.1.1",
    "@angular/forms": "~12.2.0",
    "@angular/platform-browser": "~12.2.0",
    "@angular/platform-browser-dynamic": "~12.2.0",
    "@angular/router": "~12.2.0",
    "rxjs": "~6.6.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4",
    "firebase": "^9.1.0",
    "rxfire": "^6.0.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~12.2.7",
    "@angular/cli": "~12.2.7",
    "@angular/compiler-cli": "~12.2.0",
    "@types/jasmine": "~3.8.0",
    "@types/node": "^12.11.1",
    "jasmine-core": "~3.8.0",
    "karma": "~6.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "~1.7.0",
    "typescript": "~4.3.5"
  }
}
vxqlmq5t

vxqlmq5t1#

修复方法其实很简单...
在您应用程序.模块.ts
进口

import { FIREBASE_OPTIONS } from '@angular/fire/compat';

然后将其添加到提供程序

providers: [
    { provide: FIREBASE_OPTIONS, useValue: environment.firebase }
],
a2mppw5e

a2mppw5e2#

AngularFire似乎正在进行主要的更改,包括Firebase的新模块化API,但文档还没有完全跟上。要点是,您正在使用新API初始化Firebase应用程序,但尝试使用旧API的Firebase资源。
关键是要看导入语句。比较新旧风格的初始化应用:

import {AngularFireModule} from '@angular/fire/compat';

[...]

imports: [
    AngularFireModule.initializeApp(environment.firebase),
]

import {initializeApp, provideFirebaseApp} from '@angular/fire/app';

[...]

imports: [
    provideFirebaseApp( () => initializeApp(environment.firebase)),
]

请注意旧式的初始化是如何在“compat”命名空间下进行的。如果您以这种方式初始化应用,您 * 必须 * 也使用compat库来访问资源。例如,从AngularFire docs

import {AngularFirestore, AngularFirestoreDocument} from '@angular/fire/compat/firestore';

[...]

constructor(private afs: AngularFirestore) {
    this.itemDoc = afs.doc<Item>('items/1');
    this.item = this.itemDoc.valueChanges();
  }

但是,这不适用于新风格的应用初始化,相反,您必须使用类似于Firebase docs的代码:

import {doc, Firestore, getDoc} from '@angular/fire/firestore';

[...]

constructor(private firestore: Firestore) { }

[...]

const docRef = doc(this.firestore, "cities", "SF");
const docSnap = await getDoc(docRef);

为什么这很重要?我假设,但不知道,应用程序的示例不会在新旧之间共享。
这个故事的寓意是

  • 互联网上的大多数文档都使用旧的API。如果你想使用那个API,请使用库的“Compat”版本。
  • 如果你想使用现代的模块化API,确保你没有使用“compat”库,最好的办法是参考Firebase文档,直到AngularFire团队有机会赶上。
8ftvxx2r

8ftvxx2r3#

我今天也有同样的问题,我同意:有很多版本,他们的文档令人失望。

解决方案(在我的情况下)

对于我的设置(Angular 11 +Angular /火6.1.5),我必须在我的app.module.ts文件中放入以下内容:

...
    imports: [
        ...
        AngularFireModule.initializeApp(environment.firebase),
    ],
...

(For我的environment.firebase包含我的firebase配置。)

下面对问题进行进一步分析,不在意的可以停止阅读

angular/fire 7的文档将告诉您如何执行此操作:

provideFirebaseApp(() => initializeApp(environment.firebase)),

我确信这对版本7来说效果很好,但是angular 11会自动安装版本6,因为这是兼容的。

kq0g1dla

kq0g1dla4#

当我使用两个初始化版本时,我的问题得到了修复

AngularFireModule.initializeApp(environment.firebase),
provideFirebaseApp(() => initializeApp(environment.firebase)),
zyfwsgd6

zyfwsgd65#

在文件app.module.ts上添加以下提供程序对象:

import { FIREBASE_OPTIONS } from '@angular/fire/compat';
 @NgModule({
  providers: [
    { provide: FIREBASE_OPTIONS, useValue: environment.firebase }   
  ],
 })

资料取自:[https://www.angularfix.com/2022/03/angular-fire-没有提供者-for.html][1]

az31mfrm

az31mfrm6#

我在使用auth-guard时遇到了同样的问题。
通过将compat放在导入路径中修复了此问题。

    • 之前**
import { hasCustomClaim, canActivate } from '@angular/fire/compat/auth-guard';
    • 之后**
import { hasCustomClaim, canActivate } from '@angular/fire/auth-guard';
kq4fsx7k

kq4fsx7k7#

根据@Daniel Eisenhardt的建议,我降低了我的Angular 版本。现在它可以工作了!Angular :~11.2.4并运行ng add@angular/fire安装了一个兼容版本的angular fire。("^6.1.5")这是我更新的文件

    • 应用程序模块. ts**
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './component/home/home.component';
import { LoginComponent } from './component/login/login.component';
import { NotFoundComponent } from './component/not-found/not-found.component';

import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireDatabaseModule } from '@angular/fire/database';
// import { AngularFireStorageModule } from '@angular/fire/storage';
import { environment } from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    LoginComponent,
    NotFoundComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase)
    AngularFirestoreModule,                                   
    AngularFireDatabaseModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
    • 包. json**
{
  "name": "evnt-mgmnt-app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.2.14",
    "@angular/common": "~11.2.14",
    "@angular/compiler": "~11.2.14",
    "@angular/core": "~11.2.14",
    "@angular/fire": "^6.1.5",
    "@angular/forms": "~11.2.14",
    "@angular/platform-browser": "~11.2.14",
    "@angular/platform-browser-dynamic": "~11.2.14",
    "@angular/router": "~11.2.14",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.11.3",
    "firebase": "^7.0 || ^8.0"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1102.13",
    "@angular/cli": "~11.2.15",
    "@angular/compiler-cli": "~11.2.14",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~6.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "~1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.1.5",
    "@angular-devkit/architect": ">= 0.900 < 0.1300",
    "firebase-tools": "^8.0.0 || ^9.0.0",
    "fuzzy": "^0.1.3",
    "inquirer": "^6.2.2",
    "inquirer-autocomplete-prompt": "^1.0.1",
    "open": "^7.0.3",
    "jsonc-parser": "^3.0.0"
  }
}
kmbjn2e3

kmbjn2e38#

此错误可能是您尚未完全迁移到v9 Firebase的信号。

v9火力基地

v9 Firebase代码https://dev.to/jdgamble555/angular-12-with-firebase-9-49a0示例

compat导入作为中间步骤

简单的第一步迁移需要将导入更改为compat版本。
保持代码工作,但你不会从v9树抖动中受益。
compat导入提供了与v8代码兼容的API但是提供方法,例如provideFirebaseApp将不起作用,直到所有导入都是v9导入,即回到不是compat导入。
因此,在所有相关代码升级到v9之前,请使用旧方法

import { AngularFireAuthModule } from '@angular/fire/compat/auth';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFirestoreModule } from '@angular/fire/compat/firestore';
import { AngularFireAuthGuardModule } from '@angular/fire/compat/auth-guard';

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule,
    AngularFireAuthModule,
    AngularFireAuthGuardModule,
  ],
  ...
})
export class AppModule { }

代码完全迁移后,返回到provide方法:

import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
import { provideAuth, getAuth } from '@angular/fire/auth';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
    // firebase
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideAuth(() => getAuth()),
    provideFirestore(() => getFirestore()),

相关问题