【问题标题】:Connect to both Firestore online and emulator at the same time?同时连接到 Firestore 在线和模拟器?
【发布时间】:2021-01-26 21:09:50
【问题描述】:

我想编写一个 CLI 脚本,将一些数据从我们的实时应用程序复制到本地 Firestore 模拟器,用于开发和测试目的。

您应该设置FIRESTORE_EMULATOR_HOST 环境变量以连接到本地模拟器的docs say——但这不允许同一个应用程序也连接到服务器。

我试过了:

const onlineApp = await admin.initializeApp(
    {
      credential: admin.credential.applicationDefault(),
      databaseURL: 'https://....firebaseio.com',
    },
    'default'
  );

process.env['FIRESTORE_EMULATOR_HOST'] = 'localhost:8080';

const emulator = await admin.initializeApp(
    {
      projectId: 'emulator',
    },
    'emulator'
  );

...但随后onlineApp 不再与在线 Firestore 对话。

是否有其他方法可以同时创建与两者的连接?

【问题讨论】:

    标签: node.js firebase google-cloud-firestore firebase-admin


    【解决方案1】:

    经过反复试验,似乎可以同时连接到两者。下面的代码首先连接到真正的 Firestore 数据库并进行所需的文档读取,然后实例化第二个客户端以与 Firestore 模拟器对话并进行写入。

    const admin = require('firebase-admin');
    const serviceAccount = require('./key.json');
    
    const f1 = async () => {
        const onlineApp = admin.initializeApp(
            {
                project: "PROJECT_ID",
                credential: admin.credential.cert(serviceAccount)
            },
            'default'
        );
        const onlineFirestore = onlineApp.firestore()
        const ondoc = await onlineFirestore.collection("XXX").doc("YYY").get()
            .then((doc) => {
                console.log(doc.data())
                return doc.data()
            });
        // Retrieve whatever needed here
    }
    
    const f2 = async () => {
        const emulator = admin.initializeApp(
            {
                project: "PROJECT_ID",
                credential: admin.credential.cert(serviceAccount)
            },
            'emulator'
        );
        process.env['FIRESTORE_EMULATOR_HOST'] = 'localhost:8080';
        const emulatorFirestore = emulator.firestore()
        await emulatorFirestore.collection("XXX").doc("YYY").set({some:"thing").then((res) => console.log(res));
    }
    
    const flow = async () => {
        await f1();
        await f2();
    }
    
    flow()
    

    我无法准确解释上述代码为何有效(如果我发现更多信息,我会更新答案)。尽管如此,我还是想提一些事情。

    • Firestore 客户端自动读取环境变量FIRESTORE_EMULATOR_HOST。看来您可以强制在设置环境变量之前通过读取第一个连接到在线的。
    • 如果FIRESTORE_EMULATOR_HOST 在执行脚本之前已经在系统中设置,它只会失败。和以前一样,客户端自己读取它,这使得 onlineApp 连接到模拟器。为防止这种情况发生,请确保在脚本运行之前停止并重新启动模拟器。
    • 出于上述原因,所有 async/await 内容都会强制执行评估顺序。

    说了这么多,我宁愿建议制作一个生产Firestore实例的export并在模拟器中使用它,这似乎更可靠。另外,请记住,模拟器有一个import/export 功能,它允许在模拟器运行期间保留数据库状态,因此可能更容易设置一次数据(手动或从普通 JS 对象)并导出它。

    【讨论】:

    • 这对我有用。特别是上面列表中的第二个要点
    猜你喜欢
    • 2020-09-22
    • 2021-09-17
    • 2020-12-26
    • 2020-06-17
    • 2022-11-11
    • 1970-01-01
    • 2015-12-29
    • 2020-09-05
    • 2021-12-16
    相关资源
    最近更新 更多