如何在快递中返回嵌套的firebase查询/保证?

时间:2017-07-14 08:05:55

标签: node.js express firebase firebase-admin

我正在使用firebase-admin处理NodeJS。我已经像这样构建了我的firebase数据库

用户节点:

user
|
+--- uid (-27JfjDfBetveYQNfStackOverFlow)
      |
      +-- firstname
      +-- lastname
      +-- mainCompanyId: ''
      +-- ....

userCompanies
|
+--- uid (-27JfjDfBetveYQNfStackOverFlow)
      |
      +--- companyId (-KnStackOverFlowF7DezRD0P) : true
      +--- companyId (-MyStackOverFlowF99ezRD0V) : true
      +--- .......... : true

companies
| 
+--- companyId (-KnStackOverFlowF7DezRD0P)
        |
        +-- name
        +-- createdAt
        +-- updatedAt
        +-- createdBy
        +-- ........

refs已在服务器上全局定义:

  • companiesRef = db.ref('公司')
  • usersRef = db.ref(' users')
  • userCompaniesRef = db.ref(' userCompanies')

我尝试做的是所有与用户相关的公司。为了加入数据,我在数据库中创建了节点 userCompanies ,并将companyId保存为密钥。一旦我检索到数据,我就会遍历密钥并通过他们的ID获取公司。在快递中,我创建了一个名为 / api / companies 的路线。如果我尝试将结果返回给客户端,我得到一个空数组。

这是我的路线:

app.get('/api/companies/', function (req, res) {

// getting the current session. The variable 'sess' is stored globally.
sess = req.session;

// get the current user from the session
var user = sess.user;

// get the mainCompanyId from the user
var mainCompanyId = user.companyId;

// prepare object to return it back
var myObj = {
    mainCompany: mainCompanyId, // ignore. Just a property to see users first created company
    companies: [], // this is the important property/array where I want to store all the companies
    someOtherProperties: true, // ignore
    ..... : .....
};

userCompaniesRef            // db.ref('userCompanies')
    .child(user.uid)        // -27JfjDfBetveYQNfStackOverFlow
    .once('value', function (userCompaniesSnap) {

        // get all companies which are related to the user
        var userCompaniesGroupList = userCompaniesSnap;

        // check if user has companies
        if (userCompaniesGroupList !== null) {

            // loop through all companies and get the companyId by Key
            userCompaniesGroupList.forEach(userCompaniesGroupListSnap => {

                var companyId = userCompaniesGroupListSnap.key; // -KnStackOverFlowF7DezRD0P

                companiesRef // db.ref('companies')
                    .child(companyId)
                    .once('value', companySnap => {

                        // get the current company
                        var company = companySnap.val();

                        // push it to the prepared object
                        myObj.companies.push(company);

                    }); // companiesRef.once('value)

            }); // userCompaniesGroupList.forEach

        } // if userCompaniesGroupList !== null

    }); // query userCompaniesRef

    res.status(200).send(myObj);
});

但是在res.send之后我得到了这个结果:

Empty Array

我不知道这是什么问题。推动工作正常。承诺完成后, myObj.companies 有一个空数组。如何处理这个嵌套查询并返回一个数组中的所有数据?

--- --- UPDATE

我已经尝试过承诺。还是一样,我得到一个空阵列。这是代码:

// prepare object to return it back
var myObj = {
    mainCompany: mainCompanyId,
    companies: []
};

var getCompanies = function () {
    return new Promise(function (resolve, reject) {

        userCompaniesRef // db.ref('userCompanies')
            .child(user.uid) // -27JfjDfBetveYQNfStackOverFlow
            .once('value', function (userCompaniesSnap) {

                if (userCompaniesSnap.val() !== null)
                    resolve(userCompaniesSnap);

            });
    });
}

var getCompaniesByList = function (companyList) {
    var companyListArray = [];
    return new Promise(function (resolve, reject) {

        // loop through all companies and get the companyId by Key
        companyList.forEach(userCompaniesGroupListSnap => {

            var companyId = userCompaniesGroupListSnap.key; // -KnStackOverFlowF7DezRD0P

            companiesRef // db.ref('companies')
                .child(companyId)
                .once('value', companySnap => {

                    // get the current company
                    var company = companySnap.val();

                    // push it to the prepared object
                    companyListArray.push(company);

                  //  updatedObjectFinal.push(myObj);

                }); // companiesRef.once('value)

        }); // userCompaniesGroupList.forEach
        resolve(companyListArray);
    });
}

getCompanies().then(function (compList) {
    console.log('compList:', compList.val());
    return getCompaniesByList(compList); // compList has the data. 
}).then(function (endResult) {

    console.log('endResult: ', endResult); // endResult is empty again..

    res.status(200).send(endResult);
});

在这种情况下,我试图通过用户ID获取所有公司。然后我试着将这个列表传递给下一个承诺,让每个公司按照他们的ID,将公司推送到一个数组并最后返回这个数组。但仍然是空的..

更新3:解决了问题

app.get('/api/companies/', function (req, res) {

// getting the current session
sess = req.session;

// save the user
var user = sess.user;
var userId = user.uid;

var getCompanies = function () {
    return new Promise(function (resolve, reject) {

        userCompaniesRef // db.ref('userCompanies')
            .child(userId) // -27JfjDfBetveYQNfStackOverFlow
            .once('value', function (userCompaniesSnap) {

                // prepare an array
                var companies = [];

                if (userCompaniesSnap.val() !== null) {

                    // loop through the keys and save the ids
                    userCompaniesSnap.forEach(function (companyItem) {
                        // console.log('companyIte,', companyItem.key);
                        companies.push(companyItem.key);
                    });

                    // get the latest item of the array to get the latest key
                    var latestCompanyId = companies[companies.length - 1]

                    // prepare optional object to resolve
                    var finalCompaniesList = {
                        companies: companies,
                        lastCompanyId: latestCompanyId
                    }

                    resolve(finalCompaniesList);

                }

            });
    });
}

var getCompaniesByList = function (companyArray) {

    var companyListArray = [];
    return new Promise(function (resolve, reject) {

        // loop through all companies and get the companyId by Key
        companyArray.companies.forEach(userCompaniesGroupList => {

            var companyId = userCompaniesGroupList; // -KnStackOverFlowF7DezRD0P

            var companyTest = companiesRef // db.ref('companies')
                .child(companyId)
                .once('value', companySnap => {

                    // get the current company
                    var company = companySnap.val();

                    // push it to the prepared object
                    companyListArray.push(company);

                    if (company.id === companyArray.lastCompanyId)
                        resolve(companyListArray); // I am resolving here now the data. 

                }); // companiesRef.once('value)

        }); // userCompaniesGroupList.forEach

    });
}

getCompanies().then(function (compList) {
    return getCompaniesByList(compList);
}).then(function (endResult) {
    res.status(200).send(endResult);
});

});

非常感谢弗兰克!我找到了解决问题的方法。我现在所做的是,在 getCompanies 我运行forEach预先填充带有ID​​的数组并获取阵列中的最新companyId。获得最新ID后,我创建了一个自定义对象,并在 latestCompanyId 中保存了最新的ID,然后返回了该数组。所以我现在知道了最新的id,我能够在snap promise中的foreach中运行 resolve 方法。

1 个答案:

答案 0 :(得分:1)

据我所知,异步编程101正在下降:数据是从Firebase异步加载的。当您编写结果时,数据尚未加载。

要解决此问题,请将响应写入将在所有数据可用时触发的回调:

userCompaniesRef            // db.ref('userCompanies')
    .child(user.uid)        // -27JfjDfBetveYQNfStackOverFlow
    .once('value', function (userCompaniesSnap) {
        // get all companies which are related to the user
        var userCompaniesGroupList = userCompaniesSnap;

        // check if user has companies
        if (userCompaniesGroupList !== null) {
            // loop through all companies and get the companyId by Key
            userCompaniesGroupList.forEach(userCompaniesGroupListSnap => {

                var companyId = userCompaniesGroupListSnap.key; // -KnStackOverFlowF7DezRD0P

                companiesRef // db.ref('companies')
                    .child(companyId)
                    .once('value', companySnap => {
                        // get the current company
                        var company = companySnap.val();

                        // push it to the prepared object
                        myObj.companies.push(company);

                        // send response to client
                        res.status(200).send(myObj);

                    }); // companiesRef.once('value)
            }); // userCompaniesGroupList.forEach
        } // if userCompaniesGroupList !== null
    }); // query userCompaniesRef
});