如何从 Angular 和 AngularFire 调用 Firebase Cloud Functions?



我正在尝试理解AngularFireFunctions文档。我做了一个新的Angular项目和一个新的Firestore数据库,安装了AngularFire和Firebase,将Firebase凭据连接到environments.ts,并初始化了firebase-functionsfirebase-adminfirestore

我修复了functions/package.json中的一个错误。初始化程序创建以下行:

"main": "lib/index.js",

应该是

"main": "src/index.ts",

我的目录结构如下所示:

myproject
+- .firebaserc    # Hidden file that helps you quickly switch between
|                 # projects with `firebase use`
|
+- firebase.json  # Describes properties for your project
|
+- functions/     # Directory containing all your functions code
|
+- node_modules/ # directory where your dependencies (declared in # package.json) are installed
|
+- package-lock.json
|
+- src/
|
+- index.js  # main source file for your Cloud Functions code
|
+- tsconfig.json  # if you chose TypeScript
|
+- package.json  # npm package file describing your Cloud Functions code

我启动了一个新的 Angular 项目,并完全按照 AngularFireFunctions 文档的建议设置app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireFunctionsModule, USE_EMULATOR } from '@angular/fire/compat/functions';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireFunctionsModule
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [
{ provide: USE_EMULATOR, useValue: ['localhost', 5001] }
]
})
export class AppModule {}

我在 HTML 视图中制作了一个按钮来调用 Firebase Cloud Function:

<div>
<button mat-raised-button color="basic" (click)='callMe()'>Call me!</button>
</div>

我按照文档的建议将firebase-functionsfirebase-admin导入index.ts。然后我取消注释了index.ts附带的默认函数并添加了一个console.log.

// The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
export const helloWorld = functions.https.onRequest((request, response) => {
console.log("Hello world!")
functions.logger.info("Hello logs!", {structuredData: true});
response.send("Hello from Firebase!");
});

最后我们到了app.component.ts.我不理解文档中提供的代码,它抛出错误,所以我编写了自己的控制器:

import { Component } from '@angular/core';
import { AngularFireFunctions } from '@angular/fire/compat/functions';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(private fns: AngularFireFunctions) {}

callMe() {
console.log("Calling...");
this.fns.httpsCallable('helloWorld');
}
}

当我运行firebase emulators:start时,我看到一条错误消息:

functions: Failed to load function definition from source: FirebaseError: Failed to load function definition from source: Failed to generate manifest from function source: SyntaxError: Unexpected token 'export'

它在app.module.tsapp.component.ts中反对这些行:

export class AppModule {}
export class AppComponent {}

这些不是错误,模拟器会恢复并启动。

✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://localhost:4000   

我单击 HTML 视图中的按钮,查看控制台日志中的Calling...,模拟器日志中没有任何反应。我希望在模拟器日志中看到Hello world。为什么我的 Angular 应用不调用 Firebase Cloud Function?

这没有定义可调用的函数:functions.https.onRequest.相反,它定义了一个常规的 HTTP 函数,您可以使用类似fetch的东西调用它。

可调用的云函数使用functions.https.onCall定义。要实现可调用函数,请查看有关编写可调用云函数的文档。


此外,此代码尚未调用该函数,而只是查找它:

this.fns.httpsCallable('helloWorld');

要调用它,您需要使用一些额外的括号来调用它,或者将其存储在变量中,然后按照文档中所示调用它。

const callable = fns.httpsCallable('my-fn-name');
this.data$ = callable({ name: 'some-data' });

我写了一个教程来回答这个问题。这是app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { environment } from '../environments/environment';
// AngularFire 7
// import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
// import { provideFirestore, getFirestore } from '@angular/fire/firestore';
// import { provideFunctions, getFunctions, connectFunctionsEmulator } from '@angular/fire/functions'; // https://firebase.google.com/docs/emulator-suite/connect_functions#instrument_your_app_to_talk_to_the_emulators
// AngularFire 6
import { AngularFireModule } from '@angular/fire/compat';
import { AngularFireFunctionsModule } from '@angular/fire/compat/functions';
import { USE_EMULATOR } from '@angular/fire/compat/functions'; // comment out to run in the cloud
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
// AngularFire 7
// provideFirebaseApp(() => initializeApp(environment.firebase)),
// provideFirestore(() => getFirestore()),
// provideFunctions(() => getFunctions()),
// AngularFire 6
AngularFireModule.initializeApp(environment.firebase),
AngularFireFunctionsModule
],
providers: [
{ provide: USE_EMULATOR, useValue: ['localhost', 5001] } // comment out to run in the cloud
],
bootstrap: [AppComponent]
})
export class AppModule { }

这使用AngularFire 6。我无法让 AngularFire 7 使用可调用函数。

这将运行模拟器中的函数。要在云中运行函数,请注释掉两行。

以下是app.component.ts

import { Component } from '@angular/core';
// AngularFire 7
// import { getApp } from '@angular/fire/app';
// import { provideFunctions, getFunctions, connectFunctionsEmulator, httpsCallable } from '@angular/fire/functions'; // https://firebase.google.com/docs/emulator-suite/connect_functions#instrument_your_app_to_talk_to_the_emulators
// import { Firestore, doc, getDoc, getDocs, collection, updateDoc } from '@angular/fire/firestore';
// AngularFire 6
import { AngularFireFunctions } from '@angular/fire/compat/functions';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
data$: any;
constructor(private functions: AngularFireFunctions) {
const callable = this.functions.httpsCallable('executeOnPageLoad');
this.data$ = callable({ name: 'Charles Babbage' });
}
callMe() {
console.log("Calling...");
const callable = this.functions.httpsCallable('callMe');
this.data$ = callable({ name: 'Ada Lovelace' });
};
}

又是这个棱角火6。变量data$处理从云函数返回的数据。

httpsCallable采用一个参数,即函数的名称。

callable执行函数并接受一个参数,即保存要发送到函数的数据的对象。

HTML 视图:

<div>
<button mat-raised-button color="basic" (click)='callMe()'>Call me!</button>
</div>
{{ data$ | async }}

该视图显示用户单击的按钮以及从函数返回的数据。

index.js功能:

// The Cloud Functions for Firebase SDK to create Cloud Functions and set up triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
// executes on page load
exports.executeOnPageLoad = functions.https.onCall((data, context) => {
console.log("The page is loaded!")
console.log(data);
console.log(data.name);
// console.log(context);
return 22
});
// executes on user input
exports.callMe = functions.https.onCall((data, context) => {
console.log("Thanks for calling!")
console.log(data);
console.log(data.name);
// console.log(context);
return 57
});

每个函数都使用https.onCall((data, context) => {}使其成为可调用的函数,即可从 Angular 调用。data是从Angular发送的数据。context是有关函数执行的元数据。每个函数返回数据显示在 HTML 视图中的数据。

要运行这些函数,请使用模拟器:

firebase emulators:start --only functions

相关内容

  • 没有找到相关文章