开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载本篇技术指南聚焦 firebase-js-sdk 仓库中firebase/database模块的核心类Database即 Firebase Realtime Database 的模块化 SDK 实例。通过阅读本文你将掌握Database类的类签名与两个公开属性app、type的含义理解getDatabase()如何创建并缓存实例、Database与底层Repo的连接关系以及goOffline()/goOnline()、connectDatabaseEmulator()等配套函数如何作用于该实例并能在实际项目中正确初始化、复用与销毁 Realtime Database 实例。Database 类的定位Realtime Database 的模块化入口Database类在官方 API 参考文档 database.database.md 中被定义为 “Class representing a Firebase Realtime Database”即一个代表 Firebase Realtime Database 实例的类。其完整类签名如下export declare class Database在仓库源码 packages/database/src/api/Database.ts#L235-L285 中该类的实际声明为export class Database implements _FirebaseService { /** Represents a Database instance. */ readonly type database; /** Track if the instance has been used (root or repo accessed) */ _instanceStarted: boolean false; /** Backing state for root_ */ private _rootInternal?: ReferenceImpl; /** hideconstructor */ constructor( public _repoInternal: Repo, /** The FirebaseApp associated with this Realtime Database instance. */ readonly app: FirebaseApp ) {} // ... }从源码可以看出两个关键事实Database实现了_FirebaseService接口这意味着它是作为 Firebase App 的一个“服务组件”存在由 Firebase 的组件注册机制统一管理详见后文“组件注册机制”一节它的构造函数带有hideconstructor标记不应由开发者直接new创建而应通过getDatabase()工厂函数获取实例。公开属性一览app 与 type官方文档为Database定义了恰好两个公开属性下表完整列出属性修饰符类型说明appreadonlyFirebaseApp与该 Realtime Database 实例关联的FirebaseApp。typereadonly未声明字面量类型表示这是一个Database实例。Database.app源码声明readonly app: FirebaseApp;app属性在构造函数中注入constructor(public _repoInternal: Repo, readonly app: FirebaseApp)用于保存创建该Database实例时所关联的FirebaseApp。它在整个实例生命周期内不可变更readonly。你可以通过它反向访问 Firebase 应用的配置例如db.app.options.databaseURL、db.app.options.projectId——这些配置在repoManagerDatabaseFromApp()中正是用于解析数据库地址见后文“实例的创建路径”。Database.type源码声明readonly type database;type是一个字面量类型常量属性值为字符串database。它的作用是为框架层提供运行时类型判别信息当 Firebase 的组件注册表需要识别某个服务实例的类型时可以通过instance.type database进行校验。类似的type字段在 Firebase 其他服务的实例上也普遍存在是模块化 SDK 中常见的实例标识模式。获取 Database 实例getDatabase() 工厂函数由于构造函数被隐藏获取Database实例的唯一标准途径是调用getDatabase()export declare function getDatabase(app?: FirebaseApp, url?: string): Database;参数说明参数类型说明appFirebaseApp可选关联的 FirebaseApp 实例省略时默认使用默认 AppgetApp()。urlstring可选要连接的 Realtime Database 实例 URL省略时 SDK 连接该 App 的默认实例。对应源码位于 packages/database/src/api/Database.ts#L323-L337export function getDatabase( app: FirebaseApp getApp(), url?: string ): Database { const db _getProvider(app, database).getImmediate({ identifier: url }) as Database; if (!db._instanceStarted) { const emulator getDefaultEmulatorHostnameAndPort(database); if (emulator) { connectDatabaseEmulator(db, ...emulator); } } return db; }典型用法import { initializeApp } from firebase/app; import { getDatabase, ref } from firebase/database; const app initializeApp({ databaseURL: https://my-app-default-rtdb.firebaseio.com }); const db getDatabase(app); // 默认数据库实例 const db2 getDatabase(app, https://my-app-other-rtdb.firebaseio.com); // 指定 URL 的独立实例需要特别注意两点url参数即组件标识符getDatabase()通过_getProvider(app, database).getImmediate({ identifier: url })获取实例url被用作组件实例的instanceIdentifier。这意味着同一个 App 下不同 URL 会创建不同的Database实例而对同一 URL 重复调用则返回已缓存的同一实例。重复初始化保护在底层repoManagerCreateRepo()中如果同一 App 同一 URL 对应的Repo已存在会抛出错误 “Database initialized multiple times. Please make sure the format of the database URL matches with each database() call.”见 packages/database/src/api/Database.ts#L200-L223因此请保证对同一数据库只使用一致的 URL 格式调用一次。实例的创建路径repoManagerDatabaseFromAppgetDatabase()最终调用的是组件工厂函数repoManagerDatabaseFromApp()packages/database/src/api/Database.ts#L118-L177其流程可以概括为确定数据库地址优先使用显式传入的url其次使用app.options.databaseURL若两者都缺失则回退为${projectId}-default-rtdb.firebaseio.com若连projectId也没有直接抛出致命错误 “Cant determine Firebase Database URL…”。解析 URL通过parseRepoInfo()将 URL 解析为RepoInfohost、namespace、是否使用 SSL 等信息见 packages/database/src/core/RepoInfo.ts#L32-L99。模拟器自动切换若进程环境中存在FIREBASE_DATABASE_EMULATOR_HOST环境变量会优先切换为http://${dbEmulatorHost}?ns${namespace}形式的模拟器地址。校验 URLvalidateUrl()校验 URL 合法性且要求 URL 必须指向数据库根节点“Database URL must point to the root of a Firebase Database (not including a child path).”。创建 Repo 并返回实例调用repoManagerCreateRepo()创建/获取Repo再return new Database(repo, app)。从中可以明确Database与Repo的关系Database是面向开发者的轻量门面facade而真正负责网络连接、数据同步、查询派发等核心逻辑的是内部的Repo。Database._repoInternal保存的就是这个Repo。Database 的内部结构与生命周期管理除了两个公开属性Database类还包含一组带下划线前缀的内部成员不属于公开 API但理解它们有助于把握实例生命周期内部成员类型作用_repoInternalRepo底层 Repo负责与服务器通信与数据同步。_instanceStartedboolean标记实例是否已启动首次访问_repo时置为true。_rootInternalReferenceImpl根节点引用Reference首次访问_root时创建。_delete()Promisevoid删除实例并断开底层 Repo 连接。_checkNotDeleted(apiName)void在已删除实例上调用 API 时抛出致命错误。延迟启动机制_repogetter 体现了“懒启动”设计packages/database/src/api/Database.ts#L252-L262get _repo(): Repo { if (!this._instanceStarted) { repoStart( this._repoInternal, this.app.options.appId, this.app.options[databaseAuthVariableOverride] ); this._instanceStarted true; } return this._repoInternal; }只有在第一次真正访问_repo或_root例如调用ref(db)、建立监听时repoStart()才会被触发。repoStart()packages/database/src/core/Repo.ts#L211-L284负责创建PersistentConnection或测试场景下的ReadonlyRestClient、挂接认证 token 变更监听与 App Check token 监听从而正式建立与服务器的连接。_rootgetter 则在首次访问时创建指向根路径空路径的ReferenceImplget _root(): ReferenceImpl { if (!this._rootInternal) { this._rootInternal new ReferenceImpl(this._repo, newEmptyPath()); } return this._rootInternal; }删除与防误用_delete()会调用repoManagerDeleteRepo()packages/database/src/api/Database.ts#L183-L191后者执行repoInterrupt(repo)断开连接并从缓存的repos表中移除该 Repo删除之后_checkNotDeleted()会拦截所有后续操作并抛出 “Cannot call … on a deleted database.” 致命错误。组件注册机制Database 如何挂载到 Firebase AppDatabase作为服务组件通过 packages/database/src/register.ts 注册到 Firebase 的组件注册表_registerComponent( new Component( database, (container, { instanceIdentifier: url }) { const app container.getProvider(app).getImmediate()!; const authProvider container.getProvider(auth-internal); const appCheckProvider container.getProvider(app-check-internal); return repoManagerDatabaseFromApp(app, authProvider, appCheckProvider, url); }, ComponentType.PUBLIC ).setMultipleInstances(true) );关键点组件名称为databaseComponentType.PUBLIC表示面向开发者公开setMultipleInstances(true)允许同一 App 下存在多个Database实例这正是getDatabase(app, url)中不同 URL 对应不同实例的机制来源工厂函数从容器中取出app、auth-internal、app-check-internal三个 Provider 后交给repoManagerDatabaseFromApp因此Database实例天然集成了 Firebase Authentication 与 App Check 的 token 提供能力。模块入口 packages/database/src/index.ts 在导入公共 API 后立即执行registerDatabase()完成自注册。公共 API 的完整导出清单见 packages/database/src/api.standalone.ts。围绕 Database 实例的配套函数Database实例是下面这些顶层函数的直接操作对象它们共同构成对连接生命周期与传输方式的管理能力。goOffline() 与 goOnline()主动控制连接export declare function goOffline(db: Database): void; export declare function goOnline(db: Database): void;goOffline(db)断开与服务器的连接。客户端默认会维持一条持久的自动重连连接在离线期间本地写入操作仍会立即触发事件并被排队等待重连后自动重试源码见 packages/database/src/api/Database.ts#L423-L427。goOnline(db)重新连接并同步离线期间累积的状态使客户端自动“追赶”上服务器packages/database/src/api/Database.ts#L440-L444。两者内部最终分别调用repoInterrupt()/repoResume()packages/database/src/core/Repo.ts#L836-L846作用于PersistentConnection的 interrupt/resume。connectDatabaseEmulator()接入模拟器export declare function connectDatabaseEmulator( db: Database, host: string, port: number, options?: { mockUserToken?: EmulatorMockTokenOptions | string; } ): void;注意该方法必须在任何其他数据库操作之前调用。源码中packages/database/src/api/Database.ts#L350-L400会检查db._instanceStarted若实例已启动且参数不同会直接抛出致命错误 “connectDatabaseEmulator() cannot initialize or alter the emulator configuration after the database instance has started.”。options.mockUserToken可用于在单元测试 Security Rules 时伪造认证 token对应 util 文档 中的EmulatorMockTokenOptions。forceWebSockets() / forceLongPolling()传输层选择export declare function forceWebSockets(): void; export declare function forceLongPolling(): void;forceWebSockets()强制使用 WebSocket 传输内部调用BrowserPollConnection.forceDisallow()forceLongPolling()强制使用 long-polling 传输若 databaseURL 中已使用 websocket 协议则会被忽略内部调用WebSocketConnection.forceDisallow()与BrowserPollConnection.forceAllow()。两个函数都会先经checkTransportInit()检查如果传输层已初始化会发出警告。实现位于 packages/database/src/api/Database.ts#L287-L310。enableLogging()调试日志开关export declare function enableLogging(enabled: boolean, persistent?: boolean): any; export declare function enableLogging(logger: (message: string) unknown): any;两种重载分别支持“布尔开关”persistent为true时刷新页面后仍记住日志状态与“自定义 logger 函数”最终委托给enableLoggingImpl()packages/database/src/api/Database.ts#L453-L467。与 Database 相关的其他核心类型在 database.md 的模块总览中Database类与以下类型共同构成firebase/database的公共 API 面了解它们有助于整体把握Database的使用场景DatabaseReference表示数据库中某个具体位置用于读写数据通过ref(db, path)或child(parent, path)获得Query / QueryConstraint对数据进行排序与过滤由orderByChild()、limitToFirst()、startAt()/endAt()/equalTo()等约束组合生成DataSnapshot读取数据时收到的不可变数据快照通过val()提取内容OnDisconnect客户端断线时自动写入/清除数据常用于在线状态presence检测ThenableReferencepush()返回的“既是 Promise 又是 Reference”的特殊类型可立即当引用使用也可 await 等待写入完成runTransaction()原子化地修改数据配合TransactionOptions/TransactionResult使用。其中push()生成的唯一键按当前时间排序且包含 72 位随机熵用于向列表追加数据时既按时间有序又难以被猜测实现见 packages/database/src/core/util/NextPushId.ts 对应的nextPushId。小结与源码阅读指引Database类是firebase/database模块中连接“Firebase App 组件体系”与“Realtime Database 底层同步引擎”的枢纽开发者通过getDatabase()获得它通过它的app属性访问关联 App、通过type属性识别实例身份而它内部持有的_repoInternalRepo则承担了全部网络通信与数据同步职责。掌握该类的实例化路径、懒启动机制与生命周期管理是正确使用 Firebase Realtime Database 模块化 SDK 的前提。如需深入源码推荐按以下顺序阅读类定义与实例工厂packages/database/src/api/Database.ts组件注册packages/database/src/register.ts底层同步引擎packages/database/src/core/Repo.ts连接信息解析packages/database/src/core/RepoInfo.ts模块入口与导出packages/database/src/index.ts、packages/database/src/api.standalone.ts官方 API 参考docs-devsite/database.database.md本主题文档、docs-devsite/database.md模块总览赞分享开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载相关推荐Free-courses-with-Certificates终极免费证书课程平台完全指南Free courses with Certificates终极免费证书课程平台完全指南 在竞争激烈的就业市场中提升技能和丰富简历变得至关重要。Free cadk-samples 零售虚拟试穿Virtual Try-OnAgent 的 design-spec.md 配置全解从 GCP 参数到双模式部署adk samples 零售虚拟试穿Virtual Try OnAgent 的 design spec.md 配置全解从 GCP 参数到双模式部署 导读示例工程PPTAgent 能做什么一张图看懂 AI PPT 生成的 5大核心能力PPTAgent 能做什么一张图看懂 AI PPT 生成的 5大核心能力 PPTAgent现已升级为 DeepPresenter是一个开源的 AI PPTAI AgentAI 应用后端上一篇SiYuan字体替换终极指南3步统一文档风格打造专属知识管理体验下一篇kOps 删除 InstanceGroup 实战指南kops delete instancegroup 命令全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考