帖子标题可能不完全准确,因为我什至不确定我的方法是否是最好的方法。我会让社区决定。
在 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"}
];
最终目标是对每个主机执行 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"}]
};
这个想法是使用类似的东西遍历对象:
for (const regionArray of Object.values(sortedByRegionObj)) {
Promise.all(
regionArray.map(function(host) {
...
(以上代码无效 - 只是描述总体思路)
创建 Promise 数组,然后使用 Promise.all...但后来我迷路了。让我困惑的部分是在尝试为 Promise.all 创建数组时拥有动态数量的对象... 我不知道如何做到这一点。
想法?
可能是这样的:
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));