Firebase Firestore 模拟器错误`主机已在 settings() 和 useEmulator() 中设置,将使用模拟器主机`
Posted
技术标签:
【中文标题】Firebase Firestore 模拟器错误`主机已在 settings() 和 useEmulator() 中设置,将使用模拟器主机`【英文标题】:Firebase Firestore emulator error `Host has been set in both settings() and useEmulator(), emulator host will be used` 【发布时间】:2021-03-11 23:38:39 【问题描述】:首先,这是我得到的完整错误。
@firebase/firestore:Firestore (8.1.1):主机已在 settings() 和 useEmulator() 中设置,将使用模拟器主机 错误 [FirebaseError]:Firestore 已启动,无法再更改其设置。您只能在调用 Firestore 对象上的任何其他方法之前修改设置。
这就是我启动模拟器的方式
const db = app.firestore();
const auth = firebase.auth();
if (process.env.NODE_ENV === 'development')
db.useEmulator('localhost', 8888);
firebase.auth().useEmulator('http://localhost:9099/');
当我第一次启动应用程序时,项目正在运行 nextjs,一切都按预期运行,但是在 next.js 页面之间进行一些刷新或导航后,我突然收到此错误。我必须杀死终端并重新开始,这很烦人我不知道 next.js 服务器是否多次运行 if (process.env.NODE_ENV === 'development')
代码,如果是这种情况,这可能是导致此错误的原因如何避免设置新的模拟器,当已经有一个时。还是与 firebase 模拟器相关的错误?
【问题讨论】:
您是否从数据库设置中启用 Persistence 参数?我找到了this GitHub issue,其中提到了 Persistence,但出现了类似的错误。 @ArtemisGeorgakopoulou 不,我实际上没有添加任何自定义设置,我只使用useEmulator
方法,但在此之前,我将开发中的本地主机添加为 js firestore().settings( host: 'http://localhost:8080', ssl: false )
但我有这个错误``` 错误 [FirebaseError]:Firestore 已启动,无法再更改其设置。您只能在调用 Firestore 对象上的任何其他方法之前修改设置。 ``` 当我使用 useEmulator 时,它经常发生,但很少发生。
1500 以上的人可以建议在 *** 上使用 Firebase-emulators 标签吗?
在“db.useEmulator('localhost', 8888);”行中,你有没有尝试过设置8080端口而不是设置中的配置?
Postgres 使用 8080,所以我将 8888 配置为 firestore 的端口
【参考方案1】:
NextJs 正在热重新加载网页,xxx.useEmulator(...)
正在为同一个 browser 实例调用两次。
Firebase 库在后台使用对当前应用的全局引用,从库的角度来看,您尝试对其进行两次或更多次初始化。
您可以使用以下代码重现此问题:
const db = app.firestore();
db.useEmulator('localhost', 8888);
db.useEmulator('localhost', 8888); // raises error
我发现的唯一解决方法是使用 window 对象来保存一个标志(如果它已被初始化),但您还必须处理 s-s-r 的边缘情况。
const db = app.firestore();
if(typeof window === 'undefined' || !window['_init'])
db.useEmulator('localhost', 8888);
if(typeof window !== 'undefined')
window['_init'] = true;
这不是上面最优雅的代码,但它修复了错误。
关键是要知道热重载是问题所在,Firebase应该只配置一次。
【讨论】:
我想将它标记为解决方案,但我想我会给它一天或更长时间以确保它是解决方案,因为我面临的错误并不总是发生。谢谢【参考方案2】:我同意@Reactgular 关于原因的评估。但在我的情况下,全局解决方案不太适合,因为错误是在测试期间抛出的,它们应该被隔离。
我还必须处理“清除仿真器数据”逻辑,与 useEmulator 相对应在每次初始化时调用。
为了解决这个问题,我发现 Firestore 对象内部的“主机”属性在我们调用 useEmulator 后发生了变化。然后我开始在命令 useEmulator 之前检查该属性。
代码如下:
import del from '../request';
async function initFirestore (config)
const suite, firestoreEmulatorHost = config;
const app, projectId = suite;
const firestore = app.firestore();
if (firestoreEmulatorHost)
plugEmulator(firestore, firestoreEmulatorHost);
await clearFirestoreEmulator(projectId, firestoreEmulatorHost);
return firestore;
export function plugEmulator (firestore, firestoreEmulatorHost)
const settingsHost = firestore._delegate._settings.host;
const isUnplugged = !settingsHost.includes(firestoreEmulatorHost);
if (isUnplugged)
firestore.useEmulator('localhost', firestoreEmulatorHost);
export function clearFirestoreEmulator (projectId, firestoreEmulatorHost)
const clearUrl = `http://localhost:$firestoreEmulatorHost/emulator/v1/projects/$projectId/databases/(default)/documents`;
return del(clearUrl);
【讨论】:
【参考方案3】:在这里尝试了几乎所有的解决方案后,它并没有真正起作用,这个错误时常发生,令人讨厌的是我不知道如何重现它,但我认为当这个页面有服务器时它会发生无论如何,我用来解决此错误的解决方案如下
const EMULATORS_STARTED = 'EMULATORS_STARTED';
function startEmulators()
if (!global[EMULATORS_STARTED])
global[EMULATORS_STARTED] = true;
firebase.firestore().useEmulator('localhost', 8888);
firebase.auth().useEmulator('http://localhost:9099/');
if (process.env.NODE_ENV === 'development')
startEmulators();
但要使其按预期工作,您需要确保所有模拟器都已启动,然后再向 next.js 服务器发出请求,因为如果此代码在模拟器启动之前执行,则 global[EMULATORS_STARTED] 将为 true 并且在这种情况下,它永远不会使用模拟器。 我已经在很多页面上对此进行了测试,其中一些页面出现了服务器端错误,并且错误没有发生,而是我得到了这些错误的日志,这是预期的行为,我不知道这些错误在申请之前首先存在这个解决方案?。
【讨论】:
我遇到了一个打字稿错误,由于某种原因阻止了它的工作,但将文件更改为 .js 并且现在可以工作了。谢谢。以上是关于Firebase Firestore 模拟器错误`主机已在 settings() 和 useEmulator() 中设置,将使用模拟器主机`的主要内容,如果未能解决你的问题,请参考以下文章
如何修复 React Native 中的 Firebase/firestore 错误?
Firebase Firestore:无法访问Firestore后端(仅限Android)
Firebase 模拟器对本地 FireStore 的请求不成功