1

I want to transfer files and folders in the project directory to object with NodeJS I want to define the 'root' folder to an object like 'treeview' However, it is recorded as 'pending' Can are help me solve this problem?

Root folder screenshot

Root folder/assets screenshot

My NodeJS Code:

import path from 'path';
import {program} from 'commander';
import fs from 'fs';
import util from 'util';

async function getChild(parent){
  const readDir = util.promisify(fs.readdir);

  const dirList = await readDir(parent);

  return dirList.map(async (name) => {
    const dir = path.join(parent, name);
    const isDir = fs.lstatSync(dir).isDirectory();
    
    if (isDir) {
      return {
        type: 'directory',
        name,
        child: getChild(dir),
      }
    } else 
      return {
        type: 'file',
        name,
        child: null,
      }
  });
}

export async function cli(args) {
  let directoryTreeView = {};
  const folderPath = path.resolve('');
  directoryTreeView = Object.assign({}, directoryTreeView, {
    type: 'directory',
    name: 'root',
    folderPath,
    childs: await getChild(folderPath)
  });
}

The result I got

{ type: 'directory',
  name: 'root',
  folderPath: 'O:\\rootFolder',
  childs:
   [ Promise { [Object] },
     Promise { [Object] },
   ] 
}

Must be

{
  type: 'directory',
  name: 'root',
  child: [
    {
      type: 'directory',
      name: 'assets',
      child: [
        {
          type: 'file',
          name: 'icon1.png'
        },
      ]
    },
    {
      type: 'file',
      name: 'icon2.png',
      child: null,
    }
  ]
}
BINFAS K
  • 246
  • 3
  • 11
Emin TAYFUR
  • 138
  • 7

1 Answers1

3

Your getChild doesn't return a promise for an array of objects, but a promise for an array of promises for objects - the map callback is async. These inner promises are never awaited. You're just mainly missing a Promise.all call in the right spot:

async function getChild(parent){
  const dirList = await fs.promises.readdir(parent);

  return Promise.all(dirList.map(async (name) => {
//       ^^^^^^^^^^^
    const dir = path.join(parent, name);
    const stat = await fs.promises.lstat(dir);
//               ^^^^^ let's do it asynchronously if we can
    
    if (stat.isDirectory()) {
      return {
        type: 'directory',
        name,
        child: await getChild(dir),
//             ^^^^^ needs to be awaited on every call
      }
    } else 
      return {
        type: 'file',
        name,
        child: null,
      }
  }));
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • the result is still the same: `{ type: 'directory', name: 'root', folderPath: 'O:\\rootFolder', childs: [ { type: 'directory', name: 'assets', child: [Promise] }, { type: 'file', name: 'icon2.png', child: null } ] }` – Emin TAYFUR Jul 24 '20 at 18:08
  • @EminTAYFUR that's not the same as in the question, it has already unwrapped the outer layer. And you seem to have missed updating the recursive `getChild(dir)` call that needs an `await`, just like the call in `cli` has one – Bergi Jul 24 '20 at 18:10