使用require-all从目录和子目录递归加载文件

时间:2019-07-11 09:26:31

标签: javascript recursion path

我要与特定条件匹配的目录和子目录中有json文件,但是我不知道如何使用子目录。

我正在使用require-all查找json文件:

const reqAll = require('require-all')({
  dirname: __dirname + '/resource',
  filter: /(.+)\.json$/,
  recursive: true
});

我的文件树是这样的:

MyDir
- file1.json
- SubDir
-- file2.json

打印reqAll将输出:

{ 
  file1: { 
    path: /first,
    body: ...some body
  },
  SubDir: { 
    file2: { 
      path: /second,
      body: ...some body
    } 
  } 
}

最初,我最初使用以下过滤器清除数据,因为我最初不使用子目录,但现在有意义。

let source = Object.values(reqAll).filter(r => {
    return r.path === req.url;
}

其中req.url是我正在发送的http请求的网址,即:localhost:8080/first,以便与我目录中的file1文件匹配。

问题在于,当我提交localhost:8080/second时,由于我无法与file2匹配,因此没有得到响应,因为它位于子目录中。同时发送localhost:8080/SubDir/file2无效。

有没有一种方法可以使它正常工作?

1 个答案:

答案 0 :(得分:2)

在您写的评论中:

  

因此,我将在localhost:8080 / first上执行HTTP GET,它将返回我file1对象的主体。实际上,这确实适用于此端点。但是,当我在localhost:8080 / second上执行HTTP GET时,无法将主体取回。

要做到这一点,您将需要对带有该path的条目进行递归搜索,这些内容与以下几行相似(请参见注释):

const repAll = { 
    file1: { 
        path: "/first"
    },
    SubDir: { 
        file2: { 
            path: "/second"
        },
        SubSubDir: {
            file3: {
                path: "/third"
            }
        }
    } 
};
const req = {};

function findEntry(data, path) {
    for (const value of Object.values(data)) {
        // Is this a leaf node or a container?
        if (value.path) {
            // Leaf, return it if it's a match
            if (value.path === path) {
                return value;
            }
        } else {
            // Container, look inside it recursively
            const entry = findEntry(value, path);
            if (entry) {
                return entry;
            }
        }
    }
    return undefined; // Just to be explicit
}

for (const url of ["/first", "/second", "/third", "fourth"]) {
    req.url = url;
    console.log(req.url + ":", findEntry(repAll, req.url));
}
.as-console-wrapper {
    max-height: 100% !important;
}

我添加了第二个子目录以确保递归继续工作,并提供了一个示例,该示例显示了如果找不到匹配的路径,您将获得的返回结果。

您当然可以通过先处理repAll然后再使用地图来构建地图,这比线性搜索要快:

const repAll = { 
    file1: { 
        path: "/first"
    },
    SubDir: { 
        file2: { 
            path: "/second"
        },
        SubSubDir: {
            file3: {
                path: "/third"
            }
        }
    } 
};

const byPath = new Map();
function indexEntries(map, data) {
    for (const value of Object.values(data)) {
        if (value) {
            // Leaf or container?
            if (value.path) {
                map.set(value.path, value);
            } else {
                indexEntries(map, value);
            }
        }
    }
}
indexEntries(byPath, repAll);

const req = {};
for (const url of ["/first", "/second", "/third", "fourth"]) {
    req.url = url;
    console.log(req.url + ":", byPath.get(req.url));
}
.as-console-wrapper {
    max-height: 100% !important;
}