简体   繁体   English

如何正确使用 Promise.all 组合两个数据集并返回单个对象?

[英]How to correctly use Promise.all to combine two datasets and return a single object?

I have an existing object data .我有一个现有的对象data I am using NodeJS async function to retrieve value of fetchResponse .我正在使用 NodeJS async函数来检索fetchResponse值。 Finally, I am trying to embed the fetchResponse to the existing data object using the following for loop最后,我尝试使用以下for loopfetchResponse嵌入到现有data对象中

for (let key in data) {
    for (let number in data[key]) {
        data[key][number].map( async d=> {
            const fetchResponse = await sequelize
                .query(await fetchHostDetails(d.Hostname), options);
        data[key][number]['Fetchresult'] =  fetchResponse;
        });
    }
}
return data;

I see that data is still having the original value and not including the key value pair Fetchresult : fetchResponse我看到data仍然具有原始值并且不包括key value pair Fetchresult : fetchResponse

I am trying to use Promise.All as below but it is still giving original data object value.我正在尝试使用Promise.All如下,但它仍然提供原始data对象值。

for (let key in data) {
    for (let number in data[key]) {
        data[key][number].map( async d=> {
            const fetchResponse = await sequelize
                .query(await fetchHostDetails(d.Hostname), options);
             await Promise.all({...d, Fetchresult : fetchResponse});
        });
    }
}
return data;

const data =
{
  "error1": {
    "7": [
      {
        "ErrorType": "Error-1A",
        "Hostname": "host123.com"
      }
    ],
    "8": [
      {
        "ErrorType": "Error-1B",
        "Hostname": "host223.com"
      },
      {
        "ErrorType": "Error-1C",
        "Hostname": "host1231.com"
      }
    ]
  }
}

I am getting below fetchResponse for hostName under Error-1A我在Error-1A下低于 hostName 的fetchResponse

const fetchResponse =
    [
      {
        "resType": "unknow data",
        "res": "missing data"
      },
      {
        "resType": "login failed",
        "res": "login with wrong userid"
      }
    ]

Similarly there will be separate fetchResponse for hostName under Error-1b and Error-1C but response format will be similar to what we have got for Error-1A .同样, Error-1bError-1C下的 hostName 将有单独的fetchResponse ,但响应格式将类似于我们为Error-1A获得的格式。

For data.error1[8] we are getting 2 values of fetchResponse but please note that those are 2 separate values for Error-1B and Error-1C .对于data.error1[8]我们得到了fetchResponse 2 个值,但请注意,这些是Error-1BError-1C两个单独的值。 One will be displayed after Error-1B and other will be displayed after Error-1C .一个将在Error-1B之后显示,另一个将在Error-1C之后显示。

It doesn't make sense to me to use await in a loop.在循环中使用await对我来说没有意义。 I'd prefer to generate a single, flat list of promises to eventually have one Promise.all that awaits them all.我更喜欢生成一个单一的、平面的Promise.all列表,最终有一个Promise.all等待它们。

Allow me to use a placeholderAsyncOperation to stand in for your fetch using the key and number.允许我使用placeholderAsyncOperation来代替您使用键和数字进行提取。 For demonstration purposes, I'll just delay a bit and then returns some object based on the parameters.出于演示目的,我将稍微延迟一下,然后根据参数返回一些对象。 I'll use your original input data though.不过,我会使用您的原始输入data

 const data = { "error1": { "7": [ { "ErrorType": "Error-1A", "Hostnames": "host123.com,hostabc.com,host33a.com..." } ], "8": [ { "ErrorType": "Error-1B", "Hostnames": "host223.com,host2c.com,host43a.com..." }, { "ErrorType": "Error-1C", "Hostnames": "host1231.com,host2abc.com,host313a.com..." } ] }, "error2": { }, "error3": { } } async function placeholderAsyncOperation(key, number, result) { await delay(1000); return {key, number, resultJSON: JSON.stringify(result)}; } const delay = time_ms => new Promise(resolve => setTimeout(resolve, time_ms)); let promises = []; for (let key in data) { for (let number in data[key]) { promises.push(data[key][number].map(val => (placeholderAsyncOperation(key, number, val)))); } } Promise.all(promises.flat()).then(result => console.table(result));

NOTE: About this snippet:注意:关于这个片段:

This uses console.table that Stack Overflow doesn't support so well yet (output embedded into the page will appear empty), so if you run this snippet in your browser you'll likely have to open your browser's built-in console before running the snippet .这使用了 Stack Overflow 尚不支持的console.table (嵌入页面的输出将显示为空),因此如果您在浏览器中运行此代码段,您可能必须在运行之前打开浏览器的内置控制台片段 Like, by pressing F12 or however your browser shows its console.就像,通过按 F12 或您的浏览器显示其控制台。

I would first of all build an array containing all the promises, along with key and index:我首先会构建一个包含所有承诺以及键和索引的数组:

let promises = [];

for (let key in data) {
  for (let number in data[key]) {
      let p = async() => {
           const fetchResponse = await sequelize.query(
               await fetchHostDetails(d.Hostname), options
           );
           return {key, number, fetchResponse};
      };
      promises.push(p);
   }
}

Now, before you inject this "fetch" data into your original data, the promises need to resolve.现在,在您将此“获取”数据注入原始数据之前,需要解析 promise。 So we use an async function:所以我们使用一个异步函数:

const merge = async (data, promises) => {
    
    // wait for all promises
    const resolvedPromises = await Promise.all(promises);

    // inject the results into "data"
    resolvedPromises.forEach(row => {
        if (row) {
            const {key, number, fetchResponse} = row;
            data[key][number]['Fetchresult'] =  fetchResponse;
        }
    });

    return data;

};

When you call this, remember it's async:当你调用它时,记住它是异步的:

merge(data, promises).then(newData => {

   console.log(newData);

});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM