提问人:Scott 提问时间:11/4/2023 最后编辑:Scott 更新时间:11/4/2023 访问量:50
ES6 号;嵌套 Promise.all(也许?
ES6; Nested Promise.all (Maybe?)
问:
帖子标题可能并不完全准确,因为我甚至不确定我的方法是否是最好的方法。我会让社区来决定。
在 React 应用程序中使用 Javascript(ES6)。 示例数据(原始):
dataArray =
[
{"uid": 3, "region": "bru", "hostname": "bru-002.domain.com", "status": "active"},
{"uid": 1, "region": "bru", "hostname": "bru-001.domain.com", "status": "disabled"},
{"uid": 4, "region": "apc", "hostname": "apc-001.domain.com", "status": "active"}
];
- 每个数组中的对象键名称都是静态的。我们可以假设如果有一个对象,它将包含键名称“hostname”等。
- 实时数据将包含每个区域的数百个条目和数十个其他对象字段(键)。与代码无关,仅供参考。
最终目标是对每个主机执行 HTTP 请求,并从请求中收集结果。该功能已经编写并正在使用中。 我遇到的脑洞大开的是将这些调用分成“按区域划分块”的 CR。换句话说,执行第一个区域的所有调用,完成后,启动下一个区域的调用,依此类推。所有调用的最终结果将进入 setState()。
现有代码使用 Promise 而不是 async/await。大多数时候我使用 await,但在某些情况下,我确实喜欢 Promise 与 .then 结合提供的清晰的代码可读性。
这是当前正在使用的代码片段。它位于 useEffect 块中。
...
Promise.all(
dataArray.map(function(host) {
if (host['status'] !== 'disabled') {
// pinger() is a function that makes the calls.
// Assume it returns what we want.
return pinger(host.hostname);
}
return ''; // Default return to satisfy map function
}))
.then(result => {
setPingedData(result); // Using a React set State
}
);
...
上面的代码有效,但整体有效。为了将其分开,我首先创建了一个新对象,该对象最终如下所示:
sortedByRegionObj =
{ "bru": [{"uid": 3, "hostname": "bru-002.domain.com", "status": "active"},
{"uid": 1, "hostname": "bru-001.domain.com", "status": "disabled"}],
"apc": [{"uid": 4, "hostname": "apc-001.domain.com", "status": "active"}]
};
- 顶级对象键名称表示“区域组”。
- 区域名称将是动态的。我们只能假设如果存在一个区域,该区域的值将是 1 个或多个对象的数组。
- 数组表示我们希望如何对 HTTP 调用进行分组。该数组将是一组 Promise。
这个想法是使用类似的东西遍历对象:
for (const regionArray of Object.values(sortedByRegionObj)) {
Promise.all(
regionArray.map(function(host) {
...
(上面的代码是无效的 - 只是描述一般的想法)
并创建 Promise 数组,然后使用 Promise.all...但后来我迷路了。难倒我的部分是在尝试为 Promise.all 创建数组时具有动态数量的对象...... 我无法思考如何做到这一点。
思潮?
答:
0赞
Hatem
11/4/2023
#1
可能是这样的:
const dataArray = [
{ uid: 3, region: "bru", hostname: "bru-003.domain.com", status: "active" },
{ uid: 3, region: "bru", hostname: "bru-002.domain.com", status: "active" },
{ uid: 1, region: "bru", hostname: "bru-001.domain.com", status: "disabled" },
{ uid: 4, region: "apc", hostname: "apc-001.domain.com", status: "active" },
];
const pingHosts = async (data) => {
const regions = new Set(data.map((d) => d.region));
const results = {};
for (const region of regions) {
results[region] = await Promise.all(
data
.filter((d) => d.status !== "disabled" && d.region === region)
.map((host) => pinger(host.hostname)),
);
}
return results;
};
// simulate network request
const pinger = (hostname) => new Promise((resolve) => {
setTimeout(() => {
console.log(`pinger: ${hostname}`);
resolve(`pinger: ${hostname}`);
}, 500);
})
console.log('results: ', await pingHosts(dataArray));
评论
Promise.all
创建数组时具有动态数量的对象“——但你已经做得很好了吗?您的工作代码处理具有动态对象数的对象,带有 .dataArray
regionArray
await
The above code is not valid- just depicting the general idea
——我认为你错了。你写的代码是你问题的答案,只是你忘记了等待-- .你基本上已经在不知不觉中回答了自己的问题。你被难住了,因为你忘记了等待Promise.all
for (.....) { let regionData = await Promise.all(....