Flutter Firebase云函数交互插件firebase_functions_interop的使用

Flutter Firebase云函数交互插件firebase_functions_interop的使用

简介

firebase_functions_interop 提供了 Firebase Functions Node.js SDK 的互操作层。通过此库,您可以使用 Dart 编写 Firebase Cloud 函数,并在 Node.js 中运行它们。这是一个早期开发预览版本,属于开源项目。

使用 1.0.0-dev.* 版本?请参阅UPGRADING.md 了解详细的变更和升级说明。

什么是这个?

firebase_functions_interop 提供了 Firebase Functions Node.js SDK 的互操作层。使用此库编写的 Firebase 函数必须编译为 JavaScript 并在 Node.js 中运行。幸运的是,许多互操作细节都由该库和 Dart SDK 的工具集处理。

以下是一个简单的 “Hello World” HTTPS 云函数示例:

import 'package:firebase_functions_interop/firebase_functions_interop.dart';

void main() {
  functions['helloWorld'] = functions.https.onRequest(helloWorld);
}

void helloWorld(ExpressHttpRequest request) {
  request.response.writeln('Hello world');
  request.response.close();
}

状态

版本 1.0.0 被认为是稳定的,但尚未功能完整。以下是按命名空间实现的功能状态报告:

  • ✅ functions
  • ✅ functions.config
  • ❌ functions.analytics
  • ✅ functions.auth
  • ✅ functions.firestore 🔥
  • ✅ functions.database
  • ✅ functions.https
  • ✅ functions.pubsub
  • ✅ functions.storage
  • ❌ functions.remoteConfig

使用方法

1. 创建初始项目

确保已安装 Firebase CLI 以及 Firebase 帐户和测试应用。更多详细信息请参阅Firebase 函数入门

$ mkdir myproject
$ cd myproject
$ firebase init functions

这将在您的项目的根目录下创建一个 functions 子目录,其中包含标准的 Node.js 包结构,包括 package.jsonindex.js 文件。

2. 初始化 Dart 项目

进入 functions 子目录并添加以下内容的 pubspec.yaml 文件:

name: myproject_functions
description: My project functions
version: 0.0.1

environment:
  sdk: '>=2.0.0-dev <3.0.0'

dependencies:
  # Firebase Functions 绑定
  firebase_functions_interop: ^1.0.0

dev_dependencies:
  # 需要将 Dart 编译为有效的 Node.js 模块。
  build_runner: ^1.0.0
  build_node_compilers: ^0.2.0

然后运行 pub get 来安装依赖项。

3. 编写基本函数

创建 functions/node/index.dart 文件并输入类似以下内容:

import 'package:firebase_functions_interop/firebase_functions_interop.dart';

void main() {
  functions['helloWorld'] = functions.https.onRequest(helloWorld);
}

void helloWorld(ExpressHttpRequest request) {
  request.response.writeln('Hello world');
  request.response.close();
}

复制粘贴也可以。

4. 构建您的函数

此库的版本 1.0.0 依赖于 Dart 2 和新的 build_runner 包。build_node_compilers 包提供了与 dart2js 和 DDC 编译器的集成,该包应该已经存在于 pubspec.yaml 文件的 dev_dependencies 中(见步骤 2)。

创建 functions/build.yaml 文件,内容如下:

targets:
  $default:
    sources:
      - "node/**"
      - "lib/**"
    builders:
      build_node_compilers|entrypoint:
        generate_for:
        - node/**
        options:
          compiler: dart2js
          # 列出任何 dart2js 特定参数,或省略。
          dart2js_args:
          - --minify

默认情况下,build_runner 使用 DDC 编译,而此时此库不支持它。上述配置使其使用 dart2js 编译 Dart。

构建命令如下:

$ cd functions
$ pub run build_runner build --output=build
5. 部署

pub run 的结果位于 functions/build/node/index.dart.js

在您的 functions/package.json 文件中,将 main 字段设置为指向此文件:

{
    "...": "...",
    "main": "build/node/index.dart.js"
}

或者,您可以替换默认的 index.js 文件:

$ cp functions/build/node/index.dart.js functions/index.js

使用 Firebase CLI 进行部署:

$ firebase deploy --only functions
6. 测试

您可以导航到部署命令打印的新 HTTPS 函数的 URL。对于 Realtime Database 函数,登录到 Firebase 控制台并尝试更改 /messages/{randomValue}/original 下的值。

7. 脚本(可选)

您可以使用 NPM 脚本来简化服务和部署函数的工作流。

更新您的 functions/package.json 文件,如下所示:

{
	"...": "...",
    "scripts": {
         "build": "pub run build_runner build --output=build",
         "watch": "pub run build_runner watch --output=build",

        "preserve": "npm run build",
        "serve": "firebase serve --only functions",

        "predeploy": "npm run build",
        "deploy": "firebase deploy --only functions",

        "preshell": "npm run build",
        "shell": "firebase experimental:functions:shell",

        "...": "..."
    }
}

示例

HTTPS 函数
import 'package:firebase_functions_interop/firebase_functions_interop.dart';

void main() {
  functions['helloWorld'] = functions.https.onRequest(helloWorld);
}

void helloWorld(ExpressHttpRequest request) {
  request.response.writeln('Hello world');
  request.response.close();
}
Realtime Database 函数
void main() {
  functions['makeUppercase'] =
      functions.database.ref('/messages/{messageId}/original').onWrite(makeUppercase);
}

FutureOr<void> makeUppercase(
    Change<DataSnapshot<String>> change, EventContext context) {
  final DataSnapshot<String> snapshot = change.after;
  var original = snapshot.val();
  var pushId = context.params['testId'];
  print('Uppercasing $original');
  var uppercase = pushId.toString() + ': ' + original.toUpperCase();
  return snapshot.ref.parent.child('uppercase').setValue(uppercase);
}
Firestore 函数
void main() {
  functions['makeNamesUppercase'] = functions.firestore
      .document('/users/{userId}').onWrite(makeNamesUppercase);
}

FutureOr<void> makeNamesUppercase(Change<DocumentSnapshot> change, EventContext context) {
  // 由于这是同一文档的更新,我们必须防止此函数写入、读取和再次写入导致无限循环。
  final snapshot = change.after;
  if (snapshot.data.getString("uppercasedName") == null) {
    var original = snapshot.data.getString("name");
    print('Uppercasing $original');

    UpdateData newData = new UpdateData();
    newData.setString("uppercasedName", original.toUpperCase());

    return snapshot.reference.updateData(newData);
  }
  return null;
}
Pubsub 函数
void main() {
  functions['logPubsub'] =
      functions.pubsub.topic('my-topic').onPublish(logPubsub);
}

void logPubsub(Message message, EventContext context) {
  print(message.json["name"]);
}
Storage 函数
void main() {
  functions['logStorage'] = functions.storage.object().onChange(logStorage);
}

void logStorage(ObjectMetadata data, EventContext context) {
  print(data.name);
}
Auth 函数
void main() {
  functions['logAuth'] = functions.auth.user().onCreate(logAuth);
}

void logAuth(UserRecord data, EventContext context) {
  print(data.email);
}

配置

Firebase SDK 提供了一种从 Firebase 函数中设置和访问环境变量的方法。

环境变量通过 Firebase CLI 设置,例如:

firebase functions:config:set some_service.api_key="secret" some_service.url="https://api.example.com"

有关更多详细信息,请参阅Firebase 文档

要在 Firebase 函数中读取这些值,请使用 functions.config

以下示例还使用了a package node_http 包,它提供了由 Node.js I/O 提供支持的 HTTP 客户端。

import 'package:firebase_functions_interop/firebase_functions_interop.dart';
import 'package:node_http/node_http.dart' as http;

void main() {
  functions['helloWorld'] = functions.https.onRequest(helloWorld);
}

void helloWorld(ExpressHttpRequest request) async {
  /// 获取环境配置
  final config = functions.config;
  final String serviceKey = config.get('someservice.key');
  final String serviceUrl = config.get('someservice.url');
  /// `http.get()` 函数由 `node_http` 包提供。
  var response = await http.get("$serviceUrl?apiKey=$serviceKey");
  // 对响应执行某些操作,例如将响应体转发给客户端:
  request.response.write(response.body);
  request.response.close();
}

更多关于Flutter Firebase云函数交互插件firebase_functions_interop的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Firebase云函数交互插件firebase_functions_interop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


firebase_functions_interop 是一个用于在 Dart 中与 Firebase Cloud Functions 进行交互的插件。它允许你在 Dart 代码中调用 Firebase Cloud Functions,并处理返回的结果。这个插件通常用于 Flutter 应用程序中,以便与 Firebase 后端进行通信。

安装

首先,你需要在 pubspec.yaml 文件中添加 firebase_functions_interop 依赖:

dependencies:
  flutter:
    sdk: flutter
  firebase_functions_interop: ^1.0.0

然后运行 flutter pub get 来安装依赖。

初始化 Firebase

在使用 firebase_functions_interop 之前,你需要确保 Firebase 已经在你的 Flutter 应用程序中初始化。通常,你可以在 main.dart 文件中进行初始化:

import 'package:firebase_core/firebase_core.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

使用 firebase_functions_interop

1. 导入包

import 'package:firebase_functions_interop/firebase_functions_interop.dart';

2. 创建 Firebase Functions 实例

final functions = FirebaseFunctions.instance;

3. 调用云函数

假设你有一个名为 myFunction 的 Firebase Cloud Function,你可以这样调用它:

void callMyFunction() async {
  try {
    final result = await functions.httpsCallable('myFunction').call();
    print('Function result: ${result.data}');
  } catch (e) {
    print('Error calling function: $e');
  }
}

4. 传递参数

你可以通过 call 方法传递参数给云函数:

void callMyFunctionWithParams() async {
  try {
    final result = await functions.httpsCallable('myFunction').call({
      'param1': 'value1',
      'param2': 'value2',
    });
    print('Function result: ${result.data}');
  } catch (e) {
    print('Error calling function: $e');
  }
}

5. 处理返回结果

云函数的返回结果可以通过 result.data 访问。你可以根据返回的数据类型进行处理。

示例

以下是一个完整的示例,展示了如何在 Flutter 应用程序中使用 firebase_functions_interop 调用 Firebase Cloud Function:

import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_functions_interop/firebase_functions_interop.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Firebase Functions Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () {
              callMyFunction();
            },
            child: Text('Call My Function'),
          ),
        ),
      ),
    );
  }
}

void callMyFunction() async {
  final functions = FirebaseFunctions.instance;
  try {
    final result = await functions.httpsCallable('myFunction').call({
      'param1': 'value1',
      'param2': 'value2',
    });
    print('Function result: ${result.data}');
  } catch (e) {
    print('Error calling function: $e');
  }
}
回到顶部