javascript - 在返回节点之前等待嵌套循环完成
问题描述
我正在尝试将三次嵌套循环中的结果推送到结果数组中,最后返回该数组。我认为拥有 .then 会实现我正在寻找的行为,但该函数会立即返回一个空数组。我尝试过使用 async/await、.map 和 for 循环的变体,但没有成功。
exports.getMasterTenantList = functions.https.onRequest((req, res) => {
let result = [];
cors(req, res, () => {
admin
.database()
.ref("/property_names")
.once("value")
.then((snapshot) => {
snapshot.forEach((childSnapshot) => {
const propertyName = childSnapshot.key;
admin
.database()
.ref(`/property_groups/${propertyName}/locations`)
.once("value")
.then((addresses) => {
return addresses.forEach((addressSnapshot) => {
const address = addressSnapshot.key;
admin
.database()
.ref(`/property_groups/${propertyName}/locations/${address}/residents`)
.once("value")
.then((residents) => {
return residents.forEach((resSnapshot) => {
result.push(resSnapshot.val().name);
});
})
.catch((error) => {
console.log(error);
});
});
})
.catch((error) => {
console.log(error);
});
});
return res.status(200).send(result);
})
.catch((error) => {
console.log(error);
});
});
});
解决方案
您的错误是它return addresses.forEach
不会返回您认为的结果。
您应该遵循您的代码并等待每个请求返回。你可以使用Promise.all
它。
我会去做这样的事情:
exports.getMasterTenantList = functions.https.onRequest(async(req, res) => {
await cors(req, res);
const snapshot = await admin
.database()
.ref('/property_names')
.once('value');
const result = await Promise.all(snapshot.forEach((childSnapshot) => {
const propertyName = childSnapshot.key;
const addresses = await admin
.database()
.ref(`/property_groups/${propertyName}/locations`)
.once('value');
return Promise.all(addresses.map(async(addressSnapshot) => {
const address = addressSnapshot.key;
const residents = await admin
.database()
.ref(`/property_groups/${propertyName}/locations/${address}/residents`)
.once('value');
return residents.map(resSnapshot => resSnapshot.val().name);
}));
}));
return res.status(200).send(result);
});
要了解它是如何工作的,请查看以下代码段示例:
const cors = () => new Promise((resolve) => setTimeout(resolve, 100));
const getSnapshot = () => new Promise((resolve) => setTimeout(() => {
resolve([{
key: 'dog',
}]);
}, 100));
const getAddress = () => new Promise((resolve) => setTimeout(() => {
resolve([{
key: '11 richmond street',
}]);
}, 100));
const getResident = () => new Promise((resolve) => setTimeout(() => {
resolve([{
val: () => ({
name: 'John doe',
}),
}]);
}, 100));
async function onRequest(res) {
await cors();
const snapshot = await getSnapshot();
const result = await Promise.all(snapshot.map(async (childSnapshot) => {
const propertyName = childSnapshot.key;
const addresses = await getAddress();
return Promise.all(addresses.map(async(addressSnapshot) => {
const address = addressSnapshot.key;
const residents = await getResident();
return residents.map(resSnapshot => resSnapshot.val().name);
}));
}));
return res.status(200).send(result);
}
onRequest({
status: () => ({
send: console.log,
}),
});
我什至会考虑将代码分解为几个函数,使其更易于阅读和理解。
function getSnapshot() {
return admin
.database()
.ref('/property_names')
.once('value');
}
function getAddressesByPropertyName(propertyName) {
return admin
.database()
.ref(`/property_groups/${propertyName}/locations`)
.once('value');
}
async function getResidentNameByAddress({
propertyName,
address,
}) {
return (await admin
.database()
.ref(`/property_groups/${propertyName}/locations/${address}/residents`)
.once('value')).map(resSnapshot => resSnapshot.val().name);
}
exports.getMasterTenantList = functions.https.onRequest(async(req, res) => {
await cors(req, res);
const snapshot = await getSnapshot();
const result = await Promise.all(snapshot.forEach(({
key: propertyName,
}) => {
const addresses = await getAddressesByPropertyName(propertyName);
return Promise.all(addresses.map(async({
key: address,
}) => {
return getResidentNameByAddress({
propertyName,
address,
});
}));
}));
return res.status(200).send(result);
});
推荐阅读
- c# - CancellationToken 不适用于 WaitForConnectionAsync
- .htaccess - htaccess 将 https www 和 http www 重定向到 https 非 www 子目录
- reactjs - react-sizeme 不测量组件的高度
- design-by-contract - 是否可以在编译时强制执行按合同设计的检查?
- python - 使用 Amazon EC2 运行多个 Python/FORTRAN 代码以进行科学计算
- c - 是否有可能拥有一个也是 CPython 模块的独立程序?
- mysql - MySQL表被指定了两次?
- python - 这个简单的加密和解密程序有什么问题?
- sql - 使用在查询中创建的新列进行过滤
- c - 为什么我的删除节点功能不适用于二叉搜索树?