You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Deno Deploy的Fresh框架中使用Firebase Admin时请求挂起的问题

在Deno Deploy的Fresh框架中使用Firebase Admin时请求挂起的问题

问题描述

我最近基于Deno Fresh框架做了个项目,用Firebase Admin在服务端从实时数据库取数据,然后渲染到页面上。本地跑和部署到自己的服务器上都没问题,但一部署到Deno Deploy,所有需要从Firebase拿数据的页面就直接挂住了。

我已经在Deno Deploy里配置了正确的Firebase Admin凭证环境变量,实时数据库的/test路径下也确实有字符串数据,而且Deno Deploy的日志里啥报错都没有。后来我加了好些console.log()排查,发现代码居然卡在了const value = (await ref.get()).val();这一行,后面的代码完全没执行。

代码示例

/firebase.ts

import { initializeApp, cert, getDatabase } from "https://www.gstatic.com/firebasejs/9.23.0/firebase-admin.js";

// 初始化Firebase Admin
const app = initializeApp({
  credential: cert(Deno.env.get("FIREBASE_CREDENTIALS")),
  // 这里之前可能没指定databaseURL?
});

export const db = getDatabase(app);

页面路由示例(/routes/test.tsx)

import { Handlers } from "$fresh/server.ts";
import { db } from "../firebase.ts";
import { ref } from "https://www.gstatic.com/firebasejs/9.23.0/firebase-admin/database.js";

export const handler: Handlers = {
  async GET(_req, ctx) {
    console.log("准备获取Firebase数据");
    const testRef = ref(db, "/test");
    console.log("已创建数据库引用");
    const value = (await testRef.get()).val(); // 代码就卡在这里了
    console.log("数据获取完成:", value);
    return ctx.render({ value });
  },
};

export default function TestPage({ value }: { value: string }) {
  return <div>从Firebase拿到的值:{value}</div>;
}

解决方案

为啥会卡?

主要问题出在Deno Deploy的边缘环境特性上——它对长连接的支持很有限,而Firebase Admin SDK的实时数据库客户端默认会试图建立长连接来获取数据,这就导致请求一直处于挂起状态,永远等不到响应。另外也有可能是咱们初始化Firebase的时候漏了关键配置,比如没指定数据库URL,或者凭证解析错了。

具体怎么改?

这里给你两个可行的方案:

方案一:改用Firebase实时数据库REST API(推荐)

既然边缘环境对长连接不友好,咱们直接用HTTP请求调用REST API就绕开这个问题了,而且实现起来也简单:

// 修改页面的handler部分
export const handler: Handlers = {
  async GET(_req, ctx) {
    const databaseURL = "你的Firebase实时数据库URL"; // 从Firebase控制台复制
    const apiKey = "你的Firebase项目API Key"; // 同样在控制台项目设置里找
    // 调用REST API获取数据
    const res = await fetch(`${databaseURL}/test.json?auth=${apiKey}`);
    if (!res.ok) {
      throw new Error(`请求失败:${res.statusText}`);
    }
    const value = await res.json();
    return ctx.render({ value });
  },
};

如果你的数据是公开可访问的,用API Key就足够;如果需要权限验证,也可以用Firebase Admin生成的自定义Token来替换auth参数。

方案二:调整Firebase Admin SDK的传输配置(可选)

要是你非得用Admin SDK,可以试试强制它用HTTP传输,而不是默认的WebSocket:

// 在/firebase.ts里初始化数据库后添加这段配置
import { setDatabaseAdminConfig } from "https://www.gstatic.com/firebasejs/9.23.0/firebase-admin/database.js";

export const db = getDatabase(app);
// 强制使用HTTP传输
setDatabaseAdminConfig(db, {
  transport: "http",
});

不过这个配置不是所有版本的Admin SDK都支持,所以还是优先推荐方案一。

额外检查点

别忘了在初始化Firebase App的时候,一定要指定databaseURL,不然SDK可能找不到你的数据库;还有,环境变量里的凭证是JSON字符串,得先解析成对象再传给cert(),比如改成cert(JSON.parse(Deno.env.get("FIREBASE_CREDENTIALS")!)),不然凭证会无效。

验证方法

改完代码重新部署到Deno Deploy,打开页面看看能不能正常加载数据,再去Deno Deploy的日志里确认,之前卡住的那行代码后面的console.log是不是能正常输出了。

备注:内容来源于stack exchange,提问作者Andrew Roberts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 14:54:43