【问题标题】:Firebase Firestore emulator error `Host has been set in both settings() and useEmulator(), emulator host will be used`Firebase Firestore 模拟器错误`主机已在 settings() 和 useEmulator() 中设置,将使用模拟器主机`
【发布时间】: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 以上的人可以建议在 StackOverflow 上使用 Firebase-emulators 标签吗?
  • 在“db.useEmulator('localhost', 8888);”行中,你有没有尝试过设置8080端口而不是设置中的配置?
  • Postgres 使用 8080,所以我将 8888 配置为 firestore 的端口

标签: reactjs firebase google-cloud-firestore next.js firebase-cli


【解决方案1】:

NextJs 正在热重新加载网页,xxx.useEmulator(...) 正在为同一个 browser 实例调用两次。

Firebase 库在后台使用对当前应用的全局引用,从库的角度来看,您尝试对其进行两次或更多次初始化。

您可以使用以下代码重现此问题:

const db = app.firestore();
db.useEmulator('localhost', 8888);
db.useEmulator('localhost', 8888); // raises error

我发现的唯一解决方法是使用 window 对象来保存一个标志(如果它已被初始化),但您还必须处理 SSR 的边缘情况。

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 并且现在可以工作了。谢谢。
    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2021-03-29
    • 2012-01-13
    • 1970-01-01
    • 2017-09-04
    相关资源
    最近更新 更多