为什么在使用管理员时 firebase return 为空

Why does firebase return null when using admin

我正在使用带有 bubble 的 firebase admin sdk 作为 nodejs 项目

这是我正在尝试的代码。这是行不通的。我在底部包含了更新的代码,但现在将保留它,希望其他人可以从我的错误中吸取教训。

function(properties, context) {
    console.log('trying')
    var list = []
    var util = require("util")

    var admin = require('firebase-admin');

    var serviceAccount = <COPIED/PASTED FROM FIREBASE>

    // Fetch the service account key JSON file contenT


    if (admin != null) {
        admin.initializeApp({
            credential: admin.credential.cert(serviceAccount),
            databaseURL: "https://login-database-brc.firebaseio.com"

        })
        list.push('logged into app')
        var db = admin.database();
        var ref = db.ref('BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data')


        ref.once('value').then((snapshot) => {
            snapshot.val().forEach(element => {
                list.push('check')
                list.push(element.Name)

            })


        });
    } else {
        list.push('nothing happened')
    }



    // As an admin, the app has access to read and write all data, regardless of Security Rules



    return {
        data: list
    }

}

规则如下

{
    "rules":{
      "BRC": {
        "$uid":{ 
            ".read": "$uid === auth.uid",
            ".write": "$uid === auth.uid"
        }
    }
}
}

我最终只在输出列表中看到 'logged in'。我希望看到数据桶中每个对象的名称 属性。

我能够使用标准 sdk 并使用密码身份验证在客户端使这项工作正常进行。我似乎无法超越初始化应用程序 Firebase 实例。

我确实有 /BRC 规则需要身份验证,但使用服务器 SDK 我认为这无关紧要

我想访问 BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data

中保存的所有对象

[更新代码以执行同步操作]

function(properties, context) {
var serviceAccount = {'jsonObjectFromFirebase'};
var list =[];

var admin = require("firebase-admin");


// Initialize the app with a service account, granting admin privileges
if (!admin.apps.length){
    initializeApp(serviceAccount)
};

// As an admin, the app has access to read and write all data, regardless of Security Rules
    
admin.database().ref('test').once('value')
    .then((snapshot) => {
    snapshot.val().forEach(element => {
        let a = element.name;
        list.push(a);
     })
    
    return_data(list)
    
});
    
function return_data (list){
    return { data: list};
};
    
function initializeApp (serviceAccount){
    admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://thunkableproject-f51d9-default-rtdb.firebaseio.com"
});
}


}

问题是现在从未调用 return_data。所以我不确定这里发生了什么。

[更新 2,再次尝试创建同步调用


var list =[]

var admin = require("firebase-admin");


// Initialize the app with a service account, granting admin privileges
if (!admin.apps.length){
    initializeApp(serviceAccount)
}

// As an admin, the app has access to read and write all data, regardless of Security Rules
    
admin.database().ref('BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data').once("value", function(snapshot){
    let element = snapshot.val()
    let list = []
    for (var key in element) {
       list.push(element[key].Name) 
    }
    
    return_data(list)
  })

    
function return_data (list){
    return { data: list}
}
    
function initializeApp (serviceAccount){
    admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: "https://login-database-brc.firebaseio.com"
});
}

这个我也试过了,没用

    
var promise = admin.database().ref('BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data').once("value");
    
promise.then(snapshot => {
    let element = snapshot.val()
    let list = []
    for (var key in element) {
       list.push(element[key].name) 
    };})
.catch(error => {
    alert(error)
});
    
return { data: list}

更新 9:23 美国东部时间 12/29/20

我想我现在正在以异步方式调用此函数,应该等待回调。现在的问题是 .then() 中的代码永远不会执行。


function getData() {
   var promise = admin.database().ref('BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data').once("value");

   promise.then(snapshot => {
      let element = snapshot.val()
      let list = []
      for (var key in element) {
         list.push(element[key].Name)
      };
      return list;
   })
      .catch(error => {
         return error
      });

   return promise;
}




getData().then((list) => {
   return { "data": list }
})

问题是您的 return { data: list }list.push(element.Name) 发生之前运行。这是因为数据是从 Firebase 异步加载的,并且超出了您预期的顺序。此行为在客户端和服务器端 SDK 上都是相同的,并且在现在大多数基于云的 API 中都是如此。

典型的解决方案是 return 承诺,而不是实际值。与其在这里解释,我建议阅读这些:

  • 关于 Promises 的 MDN 文档
  • Doug Stevenson 的优秀video series and blog post
  • Why Does Firebase Lose Reference outside the once() Function?

编辑:

在您的编辑中,您必须return 承诺。例如在这样定义的函数中:

function getData() {
  var promise = admin.database().ref('BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data').once("value");
    
  promise.then(snapshot => {
    let element = snapshot.val()
    let list = []
    for (var key in element) {
       list.push(element[key].name) 
    };
    return list;
  })
  .catch(error => {
    alert(error)
  });
    
  return promise;
}

现在您可以像这样使用此功能:

readData().then((list) => {
  console.log(data);
})

请注意(如评论中所述)这 不会 使代码同步,因为这是不可能的。它只是 return 对调用者的承诺,然后调用者 then “等待”数据可用。

如果您使用的是足够现代的平台,您可以在最后一个片段中使用 await

var list = await readData();
console.log(data);

虽然这看起来更熟悉,但它在幕后仍然做着完全相同的事情,并且不是同步的。

在一位朋友的帮助下,我得到了你的反馈 Frank van Puffelen。

function(properties, context) {
    var serviceAccount = <serviceAccountPath>


    var admin = require("firebase-admin");


    // Initialize the app with a service account, granting admin privileges
    if (!admin.apps.length) {
        initializeApp(serviceAccount)
    }

    function initializeApp(serviceAccount) {
        admin.initializeApp({
            credential: admin.credential.cert(serviceAccount),
            databaseURL: "https://login-database-brc.firebaseio.com"
        });
    }


    let list = context.async(async callback => {
        try {
            const snapshot = await admin.database().ref('BRC/4jV39aEK6jOecLdKONJMKatsEYn1/data').once("value");
            const element = snapshot.val()
            let list = []
            for (key in element) {
                list.push(element[key].Name)
            };
            callback(null, list);
        } catch (err) {
            callback(err);
        }
    })

    return {
        "data": list
    }


}