Home > Software design >  How to properly make a promise.all function with a .map?
How to properly make a promise.all function with a .map?

Time:03-11

I attempted to ask a simplified version of this here but I realized that it probably doesn't contain enough information. So unfortunately I'm just going to post the whole thing and hope that it doesn't offend anyone.

Basically I have 4 functions, with their stated purposes below:

1.InitializeDrive() takes a user email and uses Google's JWT user impersonation method to return the appropriate authorization for that user.

2.listfiles() calls on InitializeDrive() for authorization and retrieves a list of the documents associated with the associated user auth.

3.singleUserData() expects a list of the files such as that from listfiles() and refines them.

4.all_user_data() is intended to be the Promise.all async function that combines all of the aforementioned functions, and maps to an array of users getListUsers(), creating a master array containing all of the refined file data for each user.

Basically my poorly formed and ignorant question is 'how can make the all_user_data() in such a way that it will return the aforementioned master array?'. I am relatively new to async programming, and have a persistent problem getting confused with nested functions.

// loads credentials from .env file
require('dotenv').config();
const util = require('util');
const { google } = require('googleapis');
const { logger } = require('handlebars');
const { getListUsers } = require('./get_users');
const target_users = getListUsers();

function initializeDrive(version, user) {
return new Promise((resolve, reject) => {
const client_email = process.env.GOOGLE_CLIENT_EMAIL;
console.log(client_email);
// add some necessary escaping so to avoid errors when parsing the private key.
const private_key = process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n');
// impersonate an account with rights to create team drives
const emailToImpersonate = user;
const jwtClient = new google.auth.JWT(
  client_email,
  null,
  private_key,
  ['https://www.googleapis.com/auth/drive'],
  emailToImpersonate,
);
return google.drive({
  version: version,
  auth: jwtClient,
 });
 });
}

const listfiles = async (pagetokenObj, user) => {
let pageToken = '';
let version = 'v3';
if (pagetokenObj !== undefined) {
pageToken = pagetokenObj.pageToken;
}
const drive = await initializeDrive(version, user);
//const drive = initializeDrive(version,user);
return new Promise((resolve, reject) => {
drive.files.list(
  {
    pageSize: 100,
    fields:
      'nextPageToken, files(id, name, owners(emailAddress), 
  sharingUser(emailAddress), permissions)',
    ...(pageToken ? { pageToken } : {}),
  },
  function (err, { data: { nextPageToken = '', files = [] } = {} }) {
    if (err) {
      return reject(err);
    }
    if (!nextPageToken) {
      return resolve(files);
    }
    // if page token is present we'll recursively call ourselves until
    // we have a complete file list.
    return listfiles({ pageToken: nextPageToken }).then((otherfiles) => {
      resolve(files.concat(otherfiles));
    });
    },
   );
 });
};

//Function returns formatted
const singleUserData = async (files) => {
return new Promise((resolve, reject) => {
const single_user_json = await listfiles();
const res = single_user_json
  .filter((doc) => Boolean(doc.permissions))
  .map((doc) => {
    return {
      id: doc.id,
      sharedWith: doc.permissions
        .filter((permission) => permission.type === 'user')
        .map((permission) => {
          return {
            emailAddress: permission.emailAddress,
            role: permission.role || null,
          };
        }), // convert the perm object into a string (email address)
    };
  });
// this is how you get nicer console.logs instead of just [Object] and [Array] BS
// https://stackoverflow.com/a/10729284/9200245
console.log(util.inspect(res, { showHidden: false, depth: null, colors: true }));
if (err) {
    return reject(err);
  }
  if (!nextPageToken) {
    return resolve(files);
};
})
};

const all_user_data = async() => {
const users = await getListUsers();
const pagetokenObj = "{ pageToken = '' } = {}";
Promise.all(
users.map(async (pagetokenObj,user) => {
  const files = await listfiles(pagetokenObj, user);
  console.log(files);

  const singleUserData = await singleUserData(files)
  console.log(singleUserData);
  }),
 );
 console.log(users)
 }


//returnJSON();
//getListUsers();
//singleUserData();
all_user_data();

CodePudding user response:

You're almost there.

  1. Remove listfiles call in all_user_data
  2. Pass user to singleUserData
  3. Remove pagetokenObj in all_user_data
  4. Remove async and await inside users.map and return promise directly
  5. Await Promise.all, assign it to a variable and return that variable
  6. Remove unnecessary Promise wrapping in singleUserData
  7. Change function signature of singleUserData to take in a user
  8. Pass user to listfiles in singleUserData
  9. Return res instead of files in singleUserData

Here are the changes I made to all_user_data and singleUserData:

// Function returns formatted
async function singleUserData(user) {
  const single_user_json = await listfiles(user);
  const res = single_user_json
    .filter((doc) => Boolean(doc.permissions))
    .map((doc) => {
      return {
        id: doc.id,
        sharedWith: doc.permissions
          .filter((permission) => permission.type === "user")
          .map((permission) => {
            return {
              emailAddress: permission.emailAddress,
              role: permission.role || null,
            };
          }), // convert the perm object into a string (email address)
      };
    });

  return res;
};

async function getAllUserData() {
  const users = await getListUsers();
  const usersData = await Promise.all(
    users.map((user) => {
      return singleUserData(user);
    })
  );

  return usersData;
};

const usersData = await getAllUserData();

CodePudding user response:

I finally figured it out. Basically needed to await a lot more and properly declare async.

// loads credentials from .env file
require('dotenv').config();
const util = require('util');
const { google } = require('googleapis');
const { logger } = require('handlebars');
const { getListUsers } = require('./get_users');
const target_users = getListUsers();

async function initializeDrive(user) {
 // return new Promise((resolve, reject) => {
    const client_email = process.env.GOOGLE_CLIENT_EMAIL;
    console.log(user   ': '   client_email);
    // add some necessary escaping so to avoid errors when parsing the private key.
    const private_key = process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n');
    // impersonate an account with rights to create team drives
    const emailToImpersonate = await user;

    const jwtClient = new google.auth.JWT(
      client_email,
      null,
      private_key,
      ['https://www.googleapis.com/auth/drive'],
      emailToImpersonate,
    );
    return google.drive({
      version: "v3",
      auth: jwtClient,
    });
  //});
}
//
async function listfiles(pagetokenObj, user) {
    let pageToken = '';
   if (pagetokenObj !== undefined) {
      pageToken = pagetokenObj.pageToken;
   }
  const drive = await initializeDrive(user); 
  //console.log(drive)
  return new Promise((resolve, reject) => {
    drive.files.list(
      {
        pageSize: 100,
        fields:
          'nextPageToken, files(parents, id, name, properties, owners(emailAddress), sharingUser(emailAddress), permissions)',
        ...(pageToken ? { pageToken } : {}),
      },
      function (err, { data: { nextPageToken = '', files = [] } = {} }) {
        if (err) {
          return reject(err);
        }
        if (!nextPageToken) {
          return resolve(files);
        }
        // if page token is present we'll recursively call ourselves until
        // we have a complete file list.
        return listfiles({ pageToken: nextPageToken }).then((otherfiles) => {
          resolve(files.concat(otherfiles));
        });
      },
    );
  });
};

async function singleUserData(user) {
    const pagetokenObj = "{ pageToken = '' } = {}"
    const single_user_json = await listfiles(pagetokenObj, user);
 //   return new Promise ((resolve, reject) => {
  
  console.log(user  ":"   JSON.stringify(single_user_json));
  const res = await single_user_json
    .filter((doc) => Boolean(doc.permissions))
    .map((doc) => {
      return {
        id: doc.id,
        sharedWith: doc.permissions
          .filter((permission) => permission.type === 'user')
          .map((permission) => {
            return {
              emailAddress: permission.emailAddress,
              role: permission.role || null,
            };
           
          }) // convert the perm object into a string (email address)
          
      };
    });

  return JSON.stringify(res);
//})
}

async function getAllUserData() {
  try {
    const users = await getListUsers();
   // const userString = JSON.parse(users);
    console.log("test22222222222222: "   users)
    const usersData = await Promise.all(
    users.map((user) => {
      return singleUserData(user);
      
    })
     );
    console.log("["   usersData   "]");
    return usersData;
  } catch (error) {
    console.log(error);
  }
}

getAllUserData();

  • Related