Home > Software engineering >  How to asynchronously manipulate a deeply nested object by referennce
How to asynchronously manipulate a deeply nested object by referennce

Time:11-24

I am working on a gridsome project, where I am manipulating a schema and rendering pages based on that. So, I am passing a reference of schema to a function, which function will manipulate a deeply nested object like,

{
URL: "some.url"
paramas: {"some params}
}

to

{
URL: "some.url"
params: {"some params}
props:{
        data:[] || {}
    }
}

this manipulation will happen based on the URL and param, so I need to use forEach loop but unfortunately, forEach loop is not asynchronous.

Here I am out of ideas what I need to do if I want to manipulate all those objects (more than 100) from other module and it has to be asynchronous.

a demo schema:

{
      "name": "home",
      "path": "/",
      "header": "top_header",
      "footer": "bottom_footer",
      "rows": [
        {
          "row_class": "bg-white",
          "columns_class": "cols-66-33 cols-separated cols--height-equal",
          "column_1": [
            {
              "name": "Coral/HomeNews",
              "props": {
                "tag": "main"
              }
            }
          ],
         }
    ]
}

edit: So I am calling a function from other module like

await dataExtender(_schema);

which contains a function(currently I am developing it, and not complete) which is

const dataExtender = async _schema => {
  // Define forEach function

  console.log(chalk.green("Data Extending starts from module level"));

  

  await Promise.all(
    _schema.pages.forEach(async page => {
      page.rows.forEach(row => {
        row.column_1.forEach(async column => {
          if (column.url !== undefined) {
            await axios
              .post(column.url, column.param || {})
              .then(data => {
                console.log(chalk.green("Extending"));
                if (Array.isArray(data.data)) {
                  column.props.data = [...data.data];
                } else {
                  column.props.data = { ...data.data };
                }
              })
              .catch(err => {
                console.log(err);
              });
          }
        });
        if (row.column_2 !== undefined) {
          row.column_2.forEach(async column => {
            if (column.url !== undefined) {
              await axios
                .post(column.url, column.param || {})
                .then(data => {
                  column.props.data = data.data;
                })
                .catch(err => {
                  console.log(err);
                });
            }
          });
        }
      });
    }),
  );

  console.log(chalk.green("Data Extending finishes from module level"));
  return _schema;
};

CodePudding user response:

While forEach itself is not async-aware, that doesn't stop you from being able to push the asynchronous modification promises onto a list and awaiting for all of them at the end.

import axios from "axios";

async function processColumn(column) {
  const data = await axios.post(column.url, column.param || {});
  console.log(chalk.green("Extending"));
  if (Array.isArray(data.data)) {
    column.props.data = [...data.data];
  } else {
    column.props.data = { ...data.data };
  }
}

async function processColumn2(column) {
  const data = await axios.post(column.url, column.param || {});
  column.props.data = data.data;
}

const dataExtender = async (_schema) => {
  console.log(chalk.green("Data Extending starts from module level"));
  const promises = [];

  _schema.pages.forEach((page) => {
    page.rows.forEach((row) => {
      row.column_1.forEach((column) => {
        if (column.url !== undefined) {
          promises.push(processColumn(column));
        }
      });
      if (row.column_2 !== undefined) {
        row.column_2.forEach((column) => {
          if (column.url !== undefined) {
            promises.push(processColumn2(column));
          }
        });
      }
    });
  });
  await Promise.all(promises);
  console.log(chalk.green("Data Extending finishes from module level"));
  return _schema;
};
  • Related