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

Firebase Firestore setDoc() Promise无法解析问题求助

Next.js中Firestore写入无响应问题排查

问题描述

按照Firestore官方文档搭建并使用Firestore,在Next.js框架下调用createProductEntry函数后,代码中的两个console.log()均无输出,数据库也没有新增数据,表现为Promise既不解析也不拒绝。

相关代码

product.firebase.ts

import { doc, getFirestore, setDoc } from 'firebase/firestore';
import { initialize } from '@/lib/firebase.lib';
import { randomString } from '../utils';

export interface IFirebaseProduct {
  name: string;
}

export function isFirebaseProduct(obj: any): obj is IFirebaseProduct {
  return "name" in obj;
}

export async function createProductEntry(entry: IFirebaseProduct){
    const app = initialize();
    const db = getFirestore(app);

    const id: string = randomString(20, 'a');
    await setDoc(doc(db, 'products', id), entry).then(() => console.log("Added item: ", entry));
}

page.tsx

"use client";

import {
  IFirebaseProduct,
  createProductEntry,
} from "@/lib/firebase/product.firebase";
import { useState } from "react";

export default function AddProduct() {
  const [input, setInput] = useState<string>("");
  const sendData = (entry: IFirebaseProduct) => {
    try {
      createProductEntry(entry).then(() => console.log("Added item: ", entry));
    } catch (error) {
      console.log(error);
    }
  };
  return (
    <>
      <input
        type="text"
        placeholder="name"
        onChange={(e) => {
          setInput(e.target.value);
          console.log(input);
        }}
      ></input>
      <button onClick={() => sendData({ name: input })}>Submit</button>
    </>
  );
}

initialize函数(firebase.lib.ts)

export function initialize() {
  const app = initializeApp(firebaseConfig);
  if (typeof window !== "undefined") {
    // Enable analytics
    if ("measurementId" in firebaseConfig && app.options.projectId) {
      getAnalytics(app);
      getPerformance(app);
    }
  }
  console.log("Firebase succesfully initialized.");
  return app;
}

问题原因及解决方案

1. Firebase重复初始化导致未捕获错误

每次调用createProductEntry都会执行initialize(),而initialize()每次都会调用initializeApp(firebaseConfig)。Firebase不允许重复初始化同名(默认是[DEFAULT])的应用,这会抛出Firebase: Firebase App named '[DEFAULT]' already exists错误,但该错误没有被正确捕获,导致后续的setDoc代码无法执行,Promise处于未处理的拒绝状态,因此没有任何输出。

解决方案:修改initialize()为单例模式,先检查是否已存在应用实例,再决定是否初始化:

import { initializeApp, getApps, getApp } from "firebase/app";

export function initialize() {
  // 检查是否已有初始化的App实例
  if (!getApps().length) {
    const app = initializeApp(firebaseConfig);
    if (typeof window !== "undefined") {
      if ("measurementId" in firebaseConfig && app.options.projectId) {
        getAnalytics(app);
        getPerformance(app);
      }
    }
    console.log("Firebase successfully initialized.");
    return app;
  }
  // 返回已存在的App实例
  return getApp();
}

2. 异步错误未被正确捕获

sendData函数中使用try/catch包裹createProductEntry的调用,但createProductEntry是异步函数,直接调用而不使用await的话,try/catch无法捕获其内部的异步错误,错误只能通过.catch()方法捕获。

解决方案:改用await配合try/catch处理异步错误:

const sendData = async (entry: IFirebaseProduct) => {
  try {
    await createProductEntry(entry);
    console.log("Added item: ", entry);
  } catch (error) {
    console.error("Error adding product:", error);
  }
};

或者在.then()后添加.catch()捕获错误:

const sendData = (entry: IFirebaseProduct) => {
  createProductEntry(entry)
    .then(() => console.log("Added item: ", entry))
    .catch(error => console.error("Error adding product:", error));
};

3. 额外提示:React状态更新的异步性

onChange事件中的console.log(input)输出的是更新前的旧值,因为setState是异步操作。如果需要查看最新的输入值,可以直接打印e.target.value:

onChange={(e) => {
  setInput(e.target.value);
  console.log(e.target.value); // 输出最新值
}}

总结

核心问题是Firebase应用重复初始化导致未捕获的错误,以及异步错误处理不当。修复这两个问题后,数据写入和日志输出应该能正常工作。

内容的提问来源于stack exchange,提问作者stealing_society

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 21:15:16