“由于客户端脱机,无法获取文档”Firestore模拟器出现Firebase错误

kpbwa7wx  于 2023-10-22  发布在  其他
关注(0)|答案(3)|浏览(132)

编辑:我知道这是与模拟器的东西,因为它的工作没有他们的罚款。
我跟随一个course for Next js,我使用Firebase模拟器(它建议这样做,但没有教程这样做,因为它很容易),我试图从firestore读取一些数据的用户,但它总是得到错误,Failed to get document because the client is offline。auth模拟器工作正常,但firestore模拟器不行。即使我与互联网断开连接(我不是因为我写这个问题,可以访问任何网站)idk为什么它会有这个错误,因为网站是托管在下一个js。下面是我在课程中制作的连接到firebase的自定义钩子:

import { initializeApp } from "firebase/app";
import {
    getAuth,
    signInWithPopup,
    signOut,
    signInAnonymously,
    GoogleAuthProvider,
    connectAuthEmulator,
} from "firebase/auth";
import { getFirestore, doc, onSnapshot, connectFirestoreEmulator, getDoc } from "firebase/firestore";

const firebaseConfig = {
    apiKey: "MY APIKEY",
    authDomain: "My AUTH DOMAIN",
    projectId: "nextfirE (in the course i am using we are making are making a blog type app called nextfire)",
    storageBucket: "STOREAGEBUKET DOMAIN",
    messagingSenderId: "messagingSenderId",
    appId: "aPP id",
    measurementId: "measurementId",
};

const firebase = initializeApp(firebaseConfig);
const auth = getAuth();
const db = getFirestore()
export {
    GoogleAuthProvider,
    auth,
    signInWithPopup,
    signOut,
    signInAnonymously,
    db,
    doc,
    onSnapshot,
    getDoc
};

if (window.location.hostname === "localhost") {
    connectAuthEmulator(auth, "http://localhost:9099");
    connectFirestoreEmulator(db, "https://localhost", 8080)
}

这是一个用户名表单,这里是处理表单的react组件:

function Username() {
    const [formValue, setFormValue] = useState("");
    const [isValid, setIsValid] = useState(false);
    const [loading, setLoading] = useState(false);

    const { user, username } = useContext(UserContext);

    useEffect(() => {
        checkUsername(formValue);
    }, [formValue]);

    const onChange = (e) => {
        const val = e.target.value.toLowerCase();
        const regex = /^(?=[a-zA-Z0-9._]{3,15}$)(?!.*[_.]{2})[^_.].*[^_.]$/;

        if (val.length < 3) {
            setFormValue(val);
            setLoading(false);
            setIsValid(false);
        }

        if (regex.test(val)) {
            setFormValue(val);
            setLoading(true);
            setIsValid(false);
        }
    };

    const checkUsername = useCallback(
        debounce(async (username: string) => {
            if (username.length >= 3) {
                const ref = doc(db, `usernames/${username}`);
                const docSnap = await getDoc(ref);

                if (docSnap.exists()) {
                    setIsValid(true);
                    setLoading(false);
                } else {
                    setIsValid(false);
                    setLoading(false);
                }
            }
        }, 500),
        []
    );

    return (
        !username && (
            <section>
                <h3>Choose Your Username</h3>
                <form>
                    <input
                        name="username"
                        placeholder="username"
                        value={formValue}
                        onChange={onChange}
                    />
                    <button
                        type="submit"
                        className="btn-green"
                        disabled={!isValid}
                    >
                        Take Username
                    </button>

                    <h3>Debug State</h3>
                    <div>
                        Username: {formValue}
                        <br />
                        Loading: {loading.toString()}
                        <br />
                        Username Valid: {isValid.toString()}
                    </div>
                </form>
            </section>
        )
    );
}

它有一些正则表达式检查和长度检查,但如果它通过这些去firestore,当我输入一个已经采取的用户名时(如果它已经采取了,将有一个firestore文档存在,用户名作为文档的名称),它需要几秒钟才能显示错误,但当我输入一个尚未采取的有效用户名时,它会立即给我一个错误。你能帮帮我吗
谢谢

6pp0gazn

6pp0gazn1#

由于客户端脱机,无法获取文档
当您尝试检索单个文档,您处于脱机状态,并且请求的文档不在本地缓存中时,会发生错误。在这种情况下,客户端没有关于文档的信息,也不知道它是否存在于后端。在重新建立网络连接之前,无法知道文档是否存在。因此,为了避免错误地报告文档不存在,会产生此错误。
通过在联机状态下获取文档,使其存在于本地缓存中,可以在很大程度上避免这种情况。然而,请注意,本地高速缓存是高速缓存,并且“陈旧”条目可以从该高速缓存中被逐出,以便为其他数据腾出空间。如果文档中的数据不经常更改,您还可以通过addSnapshotListener()注册快照侦听器,并保持侦听器活动,以确保文档保留在本地缓存中。此外,可能有多种其他原因导致此错误,其中一些是:
1.您试图引用尚未创建的集合/文档。因此,只需创建一个带有虚拟文档的集合,或者等待文档创建并查看它是否正常工作。
1.执行尝试...捕获所有get().await()调用。未处理的异常可能导致此错误
1.已通过更改模拟器的端口号修复问题。如果8080不工作,请尝试8081,
此外,根据Firebase文档和GitHub链接更改,

if (window.location.hostname === "localhost") {
 connectAuthEmulator(auth, "http://localhost:9099");
 connectFirestoreEmulator(db, "https://localhost", 8080) }

if (window.location.hostname === "localhost") { 
connectAuthEmulator(auth, "http://localhost:9099"); 
connectFirestoreEmulator(db, "localhost", 8080) }

1.更新所有包并为您的Web应用启用离线持久化,如下所示:
firebase.firestore().enablePersistence()
https://firebase.google.com/docs/firestore/manage-data/enable-offline
[5]这也可能发生,因为OnCompleteListener是在任务完成时触发的,无论是失败还是成功。为了避免这个错误,你可以使用单独的OnSuccessListenerOnFailureListener OnFailure在任务成功时调用,但是如果出现上面的错误,OnFailure会被触发,你可以在监听器的onFailure()方法中处理这个错误。
[6]在将项目ID传递给initializeApp或设置环境变量时,检查项目ID是否正确。

admin.initializeApp({ projectId: "your-project-id" });

export GCLOUD_PROJECT="your-project-id"

如果仍然面临问题,请尝试按照此documentation将您的应用连接到Firestore Emulator,我还建议启用调试日志记录,看看它是否会提示客户端无法连接的原因。

q3aa0525

q3aa05252#

多亏了Gourav B,我才找到了答案。我只需要在connectFirestoreEmulator中删除localhost前面的https://。我猜在connectFirestoreEmulator中,它们连接到https://+ host + port(host和port是第二个和第三个参数)。谢谢Gourav B!

huus2vyu

huus2vyu3#

在我的例子中,我在本地使用firebase模拟器。它总是工作得很好,但我也遇到了这个错误。问题很简单,我正在为另一个项目运行系统代理(捕获我的网络流量)。当尝试使用我的本地Firebase模拟器示例对用户进行身份验证时,这导致了 “无法获取文档,因为客户端离线” Firebase错误。

相关问题