我无法从firebase数据库获取数据

问题描述 投票:0回答:2

我是 firebase 的新手。我正在尝试使用将关联凭据发送到 firebase 的 node.js 服务器从实时数据库中检索数据,但在调用 once('value') 后,某些内容会被破坏:其返回的承诺永远不会得到解决,并且服务器会自行停止记录此消息:“进程已退出,代码为 3221226505”。

我写了以下代码:

async function testFirebase1(firebaseCredentialsObj, path) {
  let firebase = require('firebase')
  firebase.initializeApp(firebaseCredentialsObj);
  var database = firebase.database();
  var ref = database.ref(path);
  console.log(ref.toString());
  try {

    // Attempt 1 
    var prom = await ref.once('value'); 
    const data = prom.;
    console.log('data ' + data)

    // Attempt 2
    prom.then((snapshot) => {
      console.log('snapshot ' + snapshot)
    }).catch((error) => { console.log(error)} )

  } catch (error) {
    console.log(error)
  }
}

永远不会发现任何错误。 我也尝试以管理员身份获取数据,但我得到了相同的失败结果

async function testFirebase3(firebaseCredentials, serviceAccountKey, databaseURL, path) {
  const admin=require('firebase-admin');
  const serviceAccount = serviceAccountKey;
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: databaseURL
    });
    var db=admin.database();
    var userRef=db.ref(path);    
    const prom = await userRef.once('value');
    console.log(prom)
}

从once()方法返回的Promise保持悬而未决。这是它的日志:

[[PromiseStatus]]:'待处理' [[PromiseValue]]:未定义

服务器端应该以json格式获取数据库数据并将其发送给客户端。 为什么会出现这种情况?

javascript node.js firebase firebase-realtime-database firebase-authentication
2个回答
1
投票

根据您的代码,您将传统的 Promise 链接和

async
/
await
语法混合在一起,这会导致您感到困惑。

注意:在下面的代码片段中,我使用了我在本答案的末尾描述的数据库查询编码风格。

SDK初始化

首先,在

testFirebase1

testFirebase3
 中,您可以在函数中初始化默认的 Firebase 应用实例。如果您只调用任一函数一次,您不会遇到任何问题,但任何时候您再次调用它们时,它们总是会抛出一个错误,指出应用程序已经初始化。为了解决这个问题,您可以使用以下函数延迟加载这些库:

function lazyFirebase(options, name = undefined) { const firebase = require('firebase'); // alternatively use the Promise-based version in an async function: // const firebase = await import('firebase'); try { firebase.app(name); } catch (err) { firebase.initializeApp(options, name); } return firebase; } function lazyFirebaseAdmin(options, name = undefined) { const admin = require('firebase-admin'); // alternatively use the Promise-based version in an async function: // const admin = await import('firebase-admin'); try { admin.app(name); } catch (err) { const cred = options.credential; if (typeof cred === "string") { options.credential = admin.credential.cert(cred) } admin.initializeApp(options, name); } return admin; }

重要提示: 上述两个函数都不会检查它们是否使用相同的 options

 对象来初始化它们。它只是假设它们是相同的配置对象。

纠正

testFirebase1

testFirebase1

中,您正在初始化默认的Firebase应用程序实例,然后
开始从数据库获取数据的过程。因为您还没有从函数中的 ref.once('value')
 返回承诺,所以调用者将得到一个 
Promise<undefined>
,它会在数据库调用完成之前解析。

async function testFirebase1(firebaseCredentialsObj, path) { let firebase = require('firebase') // bug: throws error if initializeApp called more than once firebase.initializeApp(firebaseCredentialsObj); // bug: using `var` - use `const` or `let` var database = firebase.database(); var ref = database.ref(path); console.log(ref.toString()); try { // Attempt 1 // bug: using `await` here, makes this a DataSnapshot not a Promise<DataSnapshot> // hence `prom` should be `snapshot` // bug: using `var` - use `const` or `let` var prom = await ref.once('value'); // bug: syntax error, assuming this was meant to be `prom.val()` const data = prom.; console.log('data ' + data) // Attempt 2 // bug: a `DataSnapshot` doesn't have a `then` or `catch` method // bug: if `prom` was a `Promise`, you should return it here prom .then((snapshot) => { console.log('snapshot ' + snapshot) }) .catch((error) => { console.log(error) }) } catch (error) { console.log(error) } }
纠正这些问题(并在处理 RTDB 查询时利用我的编码风格)可以得到:

async function testFirebase1(firebaseCredentialsObj, path) { const firebase = lazyFirebase(firebaseCredentialsObj); const snapshot = await firebase.database() .ref(path) .once('value'); // returns data at this location return snapshot.val(); }
纠正

testFirebase3

testFirebase3

 中,您正在初始化默认的 Firebase 管理应用实例并正确等待来自数据库的数据。因为您尚未从数据库返回数据,所以调用者将得到一个 
Promise<undefined>
,该值会在数据库调用完成时解析,但不包含包含的数据。

async function testFirebase3(firebaseCredentials, serviceAccountKey, databaseURL, path) { const admin = require('firebase-admin'); // note: unnecessary line, either call `serviceAccountKey` `serviceAccount` or use `serviceAccountKey` as-is const serviceAccount = serviceAccountKey; // bug: throws error if initializeApp called more than once // bug: `firebaseCredentials` is unused // note: when initializing the *default* app's configuration, you // should specify all options to prevent bugs when using // `admin.messaging()`, `admin.auth()`, `admin.storage()`, etc // as they all share the default app instance admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: databaseURL }); // bug: using `var` - use `const` or `let` var db=admin.database(); var userRef=db.ref(path); // bug: using `await` here, makes this a DataSnapshot not a Promise<DataSnapshot> // hence `prom` should be `snapshot` const prom = await userRef.once('value'); // bug: logging a `DataSnapshot` object isn't useful because it // doesn't serialize properly (it doesn't define `toString()`, // so it will be logged as "[object Object]") console.log(prom) }
纠正这些问题(并在处理 RTDB 查询时利用我的编码风格)可以得到:

async function testFirebase3(firebaseCredentials, serviceAccountKey, databaseURL, path) { const admin = lazyFirebaseAdmin({ ...firebaseCredentials, // note: assuming `firebaseCredentials` is the complete app configuration, credential: serviceAccountKey, databaseURL: databaseURL }); const snapshot = await admin.database() .ref(path) .once('value'); return snapshot.val(); }
    

0
投票
我也遇到过类似的问题。 我花了几个小时调查问题出在哪里。现在我想分享一下结果: 如果你的database().ref('...').once('value').then(() => {...一些代码...});永远悬而未决,首先,检查您的 firebase 规则 - 您可能禁止从 ref('...') 获取值。 这就是我的情况。 我希望我的回答能节省别人的时间

© www.soinside.com 2019 - 2024. All rights reserved.