Search code examples
javascriptnode.jsforeach

Alternative to call another async function inside 2 forEach loops


I'm trying to call a function inside a forEach loop, which is inside another forEach loop, but it doesn't return/invoke the function.

I have looked at this question but as I'm still a novice I cant seem to make it work.

This is my code (it returns password credentials for each service principle in azure, then checks the expiry date and outputs based on the difference of that date and the day of the run). I want to fire an API call to JIRA to create a ticket if it falls within the first 2 if conditions.

const execute = async () => {
  allAdApps = await exec('az ad app list --all');
  const allAdAppsJson = JSON.parse(allAdApps);

  const servicePrinciples = allAdAppsJson.filter((app) => app.displayName);
  servicePrinciples.forEach((sp) => {
    sp.passwordCredentials.forEach((passwordCred) => {
      const formatExpiryDate = new Date(passwordCred.endDateTime);
      const diffInTime = formatExpiryDate.getTime() - currentDate.getTime();
      const diffInDays = Math.floor(diffInTime / msInOneDay);

      if (diffInDays <= 30 && diffInDays > 0) {
        const logStr2 = `${sp.displayName}' will expire in '${diffInDays}' days.`;
        logger.info(logStr2);
        // my function call here
        const output = jiraCheckDuplicate('Ticket title');
      } else if (diffInDays < 0) {
        const expStr = `'${sp.displayName}' already expired '${diffInDays}' days ago.`;
        logger.info(expStr);
        // my function call here
        const output = jiraCheckDuplicate('Ticket title');
      } else {
        logger.info('string');
      }
    });
  });

};

execute()
  .then(() => process.exit())
  .catch((err) => {
    logger.error(err.message);
    process.exit(1);
  });

I have tried to change the forEach to a for of, but still getting no response from my function

const execute = async () => {
  allAdApps = await exec('az ad app list --all');
  const allAdAppsJson = JSON.parse(allAdApps);

  const servicePrinciples = allAdAppsJson.filter((app) => app.displayName);
  for (const sp of servicePrinciples) {
    for (const passwordCred of sp.passwordCredentials) {
      const formatExpiryDate = new Date(passwordCred.endDateTime);
      const diffInTime = formatExpiryDate.getTime() - currentDate.getTime();
      const diffInDays = Math.floor(diffInTime / msInOneDay);

      if (diffInDays <= 30 && diffInDays > 0) {
        const logStr2 = `${sp.displayName}' will expire in '${diffInDays}' days.`;
        logger.info(logStr2);
        // my function call here
        await jiraCheckDuplicate('Ticket title', user, token);
      } else if (diffInDays < 0) {
        const expStr = `'${sp.displayName}' already expired '${diffInDays}' days ago.`;
        logger.info(expStr);
        // my function call here
        await jiraCheckDuplicate('Ticket title', user, token);
      } else {
        logger.info('string');
      }
    }
  }
};

execute()
  .then(() => process.exit())
  .catch((err) => {
    logger.error(err.message);
    process.exit(1);
  });

I've tried using .map and promises, but again to no avail. (See this question)

const execute = async () => {
  allAdApps = await exec('az ad app list --all');
  const allAdAppsJson = JSON.parse(allAdApps);

  const servicePrinciples = allAdAppsJson.filter((app) => app.displayName);
  const promises2 = servicePrinciples.map(async (sp) => {
    const promises = sp.passwordCredentials.map(async (passwordCred) => {
      const formatExpiryDate = new Date(passwordCred.endDateTime);
      const diffInTime = formatExpiryDate.getTime() - currentDate.getTime();
      const diffInDays = Math.floor(diffInTime / msInOneDay);

      if (diffInDays <= 30 && diffInDays > 0) {
        const logStr2 = `${sp.displayName}' will expire in '${diffInDays}' days.`;
        logger.info(logStr2);
        // my function call here
        await jiraCheckDuplicate('Ticket title', user, token).promise();
      } else if (diffInDays < 0) {
        const expStr = `'${sp.displayName}' already expired '${diffInDays}' days ago.`;
        logger.info(expStr);
        // my function call here
        await jiraCheckDuplicate('Ticket title', user, token).promise();
      } else {
        logger.info(logStr);
      }
    });
    await Promise.all(promises);
  });
};

execute()
  .then(() => process.exit())
  .catch((err) => {
    logger.error(err.message);
    process.exit(1);
  });



I've simplified my function to a 'hello world' output to eliminate any possible error in the cURL request - the function does work when calling outside the for loops

const jiraCheckDuplicate = async (
  summary,
  user,
  token,
) => {
  const auth = `${user}:${token}`;

  const urlSummary = encodeURIComponent(summary);

  fetch(`https://enterprisevm.atlassian.net/rest/api/2/search?jql=summary~%22'${urlSummary}'%22+and+status!="Done"`, {
    method: 'GET',
    headers: {
      Authorization: `Basic ${Buffer.from(
        auth,
      ).toString('base64')}`,
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
  })
    .then((response) => {
      logger.info(
        `Response: ${response.status} ${response.statusText}`,
      );
      return response.text();
    })
    .then((text) => logger.info(text))
    .catch((err) => logger.error(err));
};

module.exports = jiraCheckDuplicate;

Solution

  • Ultimately, it came down to using:

    for (const sp of servicePrinciples) {
        for (const passwordCred of sp.passwordCredentials) {
    

    removing process.exit() and updating jiraCheckDuplicate to be an async function with return:

    const jiraCheckDuplicate = async (