ES6;嵌套 Promise.all (也许?)

问题描述 投票:0回答:1

帖子标题可能不完全准确,因为我什至不确定我的方法是否是最好的方法。我会让社区决定。

在 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"}]
};
  • 顶级对象键名称代表“区域组”。
  • 区域名称将是动态的。我们只能假设如果存在一个区域,则该区域的值将是一个包含 1 个或多个对象的数组。
  • 数组代表我们希望如何对 HTTP 调用进行分组。该数组将是一组 Promise。

这个想法是使用类似的东西遍历对象:

for (const regionArray of Object.values(sortedByRegionObj)) {
 Promise.all(
          regionArray.map(function(host) {
...

(以上代码无效 - 只是描述总体思路)

创建 Promise 数组,然后使用 Promise.all...但后来我迷路了。让我困惑的部分是在尝试为 Promise.all 创建数组时拥有动态数量的对象... 我不知道如何做到这一点。

想法?

javascript es6-promise
1个回答
0
投票

可能是这样的:

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));

演示:https://livecodes.io/?x=id/mndyfu329vr&console=open

© www.soinside.com 2019 - 2024. All rights reserved.