我如何在 express 中 return 嵌套的 firebase query/promise?
How can I return a nested firebase query/promise in express?
我正在使用 firebase-admin 开发 NodeJS。我已经像这样构建了我的 firebase 数据库
用户节点:
user
|
+--- uid (-27JfjDfBetveYQNfWhosebug)
|
+-- firstname
+-- lastname
+-- mainCompanyId: ''
+-- ....
userCompanies
|
+--- uid (-27JfjDfBetveYQNfWhosebug)
|
+--- companyId (-KnWhosebugF7DezRD0P) : true
+--- companyId (-MyWhosebugF99ezRD0V) : true
+--- .......... : true
companies
|
+--- companyId (-KnWhosebugF7DezRD0P)
|
+-- name
+-- createdAt
+-- updatedAt
+-- createdBy
+-- ........
refs 已经在服务器上全局定义:
- companiesRef = db.ref('companies')
- usersRef = db.ref('users')
- userCompaniesRef = db.ref('userCompanies')
我尝试做的是获取所有与用户相关的公司。为了加入数据,我在数据库中创建了节点 userCompanies 并将 companyId 保存为键。一旦我检索到数据,我就会遍历密钥并通过他们的 ID 获取公司。在 express 中,我创建了一条名为 /api/companies 的路线。如果我尝试 return 结果返回给客户端,我得到一个空数组。
这是我的路线:
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) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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 就会有一个空数组。如何处理这个嵌套查询和 return 一个数组中的所有数据?
---更新---
我已经尝试过承诺。还是一样,我得到一个空数组。这是代码:
// 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) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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 获取每个公司,将公司推送到一个数组,然后 return 这个数组回到最后。但是还是空的..
更新 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) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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 后,我创建了一个自定义对象并将最新 ID 保存在 latestCompanyId 中,然后 return 编辑数组。所以我现在知道了最新的 ID,并且我能够 运行 snap promise 中 foreach 内的 resolve 方法。
据我所知,您很快就会爱上异步编程 101:数据是从 Firebase 异步加载的。当您写入结果时,数据尚未加载。
要解决此问题,请将响应的写入移动到所有数据可用时触发的回调中:
userCompaniesRef // db.ref('userCompanies')
.child(user.uid) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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
});
我正在使用 firebase-admin 开发 NodeJS。我已经像这样构建了我的 firebase 数据库
用户节点:
user
|
+--- uid (-27JfjDfBetveYQNfWhosebug)
|
+-- firstname
+-- lastname
+-- mainCompanyId: ''
+-- ....
userCompanies
|
+--- uid (-27JfjDfBetveYQNfWhosebug)
|
+--- companyId (-KnWhosebugF7DezRD0P) : true
+--- companyId (-MyWhosebugF99ezRD0V) : true
+--- .......... : true
companies
|
+--- companyId (-KnWhosebugF7DezRD0P)
|
+-- name
+-- createdAt
+-- updatedAt
+-- createdBy
+-- ........
refs 已经在服务器上全局定义:
- companiesRef = db.ref('companies')
- usersRef = db.ref('users')
- userCompaniesRef = db.ref('userCompanies')
我尝试做的是获取所有与用户相关的公司。为了加入数据,我在数据库中创建了节点 userCompanies 并将 companyId 保存为键。一旦我检索到数据,我就会遍历密钥并通过他们的 ID 获取公司。在 express 中,我创建了一条名为 /api/companies 的路线。如果我尝试 return 结果返回给客户端,我得到一个空数组。
这是我的路线:
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) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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 就会有一个空数组。如何处理这个嵌套查询和 return 一个数组中的所有数据?
---更新---
我已经尝试过承诺。还是一样,我得到一个空数组。这是代码:
// 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) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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 获取每个公司,将公司推送到一个数组,然后 return 这个数组回到最后。但是还是空的..
更新 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) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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 后,我创建了一个自定义对象并将最新 ID 保存在 latestCompanyId 中,然后 return 编辑数组。所以我现在知道了最新的 ID,并且我能够 运行 snap promise 中 foreach 内的 resolve 方法。
据我所知,您很快就会爱上异步编程 101:数据是从 Firebase 异步加载的。当您写入结果时,数据尚未加载。
要解决此问题,请将响应的写入移动到所有数据可用时触发的回调中:
userCompaniesRef // db.ref('userCompanies')
.child(user.uid) // -27JfjDfBetveYQNfWhosebug
.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; // -KnWhosebugF7DezRD0P
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
});