0

I'm trying to make an Electron-Vue app that's reading directory and displays folders/files by calling this method:

load (path = 'C:') {
  path = join(path)
  this.diskLetter = path[0]
  this.$store.dispatch('getContents', path).then(() => {
    this.$store.commit('setPlacePath', path)
  }, err => {
    console.error(err)
    this.$route.push('/')
  })
}

The problem is, when I try to load a directory that has some locked files for example:

load (path = 'C:'), it throws console errors for such files, for instance:

Uncaught (in promise) Error: 
EPERM: operation not permitted, stat 'C:\System Volume Information'

But I want it to return something like this below (16 out of 21):

(which is what this project exactly does)

(21) ["$Recycle.Bin", "$SysReset", "bootmgr", "Dell", "Documents and Settings", "ESD", "ffmpeg", "hiberfil.sys", "Intel", "pagefile.sys", "PerfLogs", "Program Files", "Program Files (x86)", "ProgramData", "Python36", "Recovery", "swapfile.sys", "System Volume Information", "test", "Users", "Windows"]


Error: EBUSY: resource busy or locked, stat 'C:\hiberfil.sys'
Error: EBUSY: resource busy or locked, stat 'C:\pagefile.sys'
Error: EPERM: operation not permitted, stat 'C:\Recovery'
Error: EBUSY: resource busy or locked, stat 'C:\swapfile.sys'
Error: EPERM: operation not permitted, stat 'C:\System Volume Information'

(16) [Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats, Stats]

js file:

import fs from 'fs-extra'
import { join } from 'path'

/**
 * Get Array for path contents. Checks if path exists
 * @param  {String} path
 * @return {Promise}
 */
export function readdir (path) {
  return pathExists(path)
    ? fs.readdir(path)
    : Promise.reject(new Error('Path does not exist'))
}

/**
 * Alias of fs.existsSync
 * @param  {String} path
 * @return {Boolean}
 */
export function pathExists (path) {
  return fs.existsSync(path)
}

/**
 * Get path stat
 * @param  {String} path
 * @return {Promise}
 */
export function stat (path) {
  return fs.stat(path)
}

/**
 * Take in file path and return contents with stat
 * @param  {String} path
 * @return {Array}
 */
export default path => {
  return new Promise((resolve, reject) => {
    const contents = []

    readdir(path).then(files => {
      let statsPromises = []

      files.forEach(file => {
        statsPromises.push(stat(join(path, file)))
      })

      Promise.all(statsPromises).then(stats => {
        stats.forEach((stat, i) => {
          contents.push({
            name: files[i],
            path: join(path, files[i]),
            stat
          })
        })

        resolve(contents)        
      })
    })
  })
}
Un1
  • 3,874
  • 12
  • 37
  • 79

1 Answers1

2

Just handle the error where stat rejects, using .catch() or the second argument to .then():

export default function(path) {
  return readdir(path).then(files => {
    const statsPromises = files.map((file, i) => {
      const p = join(path, file);
      return stat(p).then(stat =>
        ({
          name: file,
          path: p,
          stat
        })
      , err => null);
//    ^^^^^^^^^^^^^
    });
    return Promise.all(statsPromises);
  }).then(contents =>
    contents.filter(Boolean)
  );
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Oh wow, I just copy/pasted that and it just works. Thank you so much, you're amazing at this! – Un1 Mar 01 '18 at 15:24
  • It's really hard to solve these problems being a newbie. People like you make it so much easier to learn, thank you for helping out new devs here, it really means a lot – Un1 Mar 01 '18 at 15:28