编辑:我知道这是与模拟器的东西,因为它的工作没有他们的罚款。
我跟随一个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文档存在,用户名作为文档的名称),它需要几秒钟才能显示错误,但当我输入一个尚未采取的有效用户名时,它会立即给我一个错误。你能帮帮我吗
谢谢
3条答案
按热度按时间6pp0gazn1#
由于客户端脱机,无法获取文档
当您尝试检索单个文档,您处于脱机状态,并且请求的文档不在本地缓存中时,会发生错误。在这种情况下,客户端没有关于文档的信息,也不知道它是否存在于后端。在重新建立网络连接之前,无法知道文档是否存在。因此,为了避免错误地报告文档不存在,会产生此错误。
通过在联机状态下获取文档,使其存在于本地缓存中,可以在很大程度上避免这种情况。然而,请注意,本地高速缓存是高速缓存,并且“陈旧”条目可以从该高速缓存中被逐出,以便为其他数据腾出空间。如果文档中的数据不经常更改,您还可以通过
addSnapshotListener()
注册快照侦听器,并保持侦听器活动,以确保文档保留在本地缓存中。此外,可能有多种其他原因导致此错误,其中一些是:1.您试图引用尚未创建的集合/文档。因此,只需创建一个带有虚拟文档的集合,或者等待文档创建并查看它是否正常工作。
1.执行尝试...捕获所有get().await()调用。未处理的异常可能导致此错误
1.已通过更改模拟器的端口号修复问题。如果8080不工作,请尝试8081,
此外,根据Firebase文档和GitHub链接更改,
到
1.更新所有包并为您的Web应用启用离线持久化,如下所示:
firebase.firestore().enablePersistence()
https://firebase.google.com/docs/firestore/manage-data/enable-offline
[5]这也可能发生,因为
OnCompleteListener
是在任务完成时触发的,无论是失败还是成功。为了避免这个错误,你可以使用单独的OnSuccessListener
和OnFailureListener
OnFailure在任务成功时调用,但是如果出现上面的错误,OnFailure会被触发,你可以在监听器的onFailure()
方法中处理这个错误。[6]在将项目ID传递给initializeApp或设置环境变量时,检查项目ID是否正确。
或
如果仍然面临问题,请尝试按照此documentation将您的应用连接到Firestore Emulator,我还建议启用调试日志记录,看看它是否会提示客户端无法连接的原因。
q3aa05252#
多亏了Gourav B,我才找到了答案。我只需要在connectFirestoreEmulator中删除localhost前面的https://。我猜在connectFirestoreEmulator中,它们连接到https://+ host + port(host和port是第二个和第三个参数)。谢谢Gourav B!
huus2vyu3#
在我的例子中,我在本地使用firebase模拟器。它总是工作得很好,但我也遇到了这个错误。问题很简单,我正在为另一个项目运行系统代理(捕获我的网络流量)。当尝试使用我的本地Firebase模拟器示例对用户进行身份验证时,这导致了 “无法获取文档,因为客户端离线” Firebase错误。