The purpose of the code is to allow the user to select directories that will be crawled recursively in order to find particular files or file types to analyze en masse. The thing to bear in mind is that if C:\
is already selected, then any child path of C:\
that the user tries to select will be discarded. The entire process of the script can be broken down into the following steps:
- The user selects a directory or directories via a dialog box.
- The script then compares the selection to whatever directories might already be stored in an array in the configuration file, which is a JSON object.
- If the selection is invalid, the selection is discarded. / If the selection is valid, the configuration file is modified accordingly.
Obviously promises are ideal, so I'm using Node's fs.promises
. However, the tricky bit is that, although they're asynchronous, parts of the code must behave synchronously. For example, it would be a waste of resources to retrieve the array from the configuration file if the dialog box is cancelled by the user.
I'm completely new to promises and everything else that entails, so I'm wondering whether or not there's an even better way to structure the asynchronous code or the code in general? The code works fine the way it is, but can its structure/readability and or efficiency be improved?
async function userSelectsArchives()
{
try {
const r1 = await dialog.showOpenDialog(remote.getCurrentWindow(), {
title: 'Select Archives to Analyze',
buttonLabel: 'Select Archives',
defaultPath: 'c:\\',
properties: [ 'openDirectory', 'multiSelections' ]
})
if (r1.canceled) throw new Error('Dialog cancelled.')
const
r2 = await fsp.readFile('./config.json', 'utf8'),
config = JSON.parse(r2),
archivesOG = config.archives
for (const dir of r1.filePaths){
// Disregard user input if parent path or exact match already exists.
if (
config.archives.reduce((a, v) => {
return a || dir.indexOf(v.slice(-1) === '\\' ? v : (v + '\\')) === 0
}, false)
|| config.archives.includes(dir)
) continue
// Remove child paths of user input in config.
config.archives = config.archives.filter(
v => v.indexOf(dir.slice(-1) === '\\' ? dir : (dir + '\\')) !== 0
)
// Add user input to archive.
config.archives.push(dir)
}
// Verify that changes have occurred or throw error.
if (archivesOG === config.archives) throw new Error('Invalid selection.')
await fsp.writeFile('./config.json', JSON.stringify(config, null, 2), 'utf8')
displayDirs(config.archives)
}
catch (error) {
console.error(error)
}
}
archivesOG === config.archives
evaluates tofalse
if or rather whenconfig.archives
is modified, which is typically the case, sincearchivesOG
is simply a cached version ofconfig.archives
before potential modifications are acted out \$\endgroup\$