我正在使用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已在服务器上全局定义:
我尝试做的是所有与用户相关的公司。为了加入数据,我在数据库中创建了节点 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之后我得到了这个结果:
我不知道这是什么问题。推动工作正常。承诺完成后, 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 方法。
答案 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
});