Вы можете упростить задачу, если вы обещаете функции fs
, которые используете, чтобы вся асинхронная логика была обещанием, а затем использовали async / await, чтобы помочь вам сериализовать поток управления.
Вот один из способов сделать это:
const promisify = require('util').promisify;
const path = require('path');
const fs = require('fs');
const readdirp = promisify(fs.readdir);
const statp = promisify(fs.stat);
async function scan(directoryName = './data', results = []) {
let files = await readdirp(directoryName);
for (let f of files) {
let fullPath = path.join(directoryName, f);
let stat = await statp(fullPath);
if (stat.isDirectory()) {
await scan(fullPath, results);
} else {
results.push(fullPath);
}
}
return results;
}
Приведенный выше код был протестирован в узле v10.14.1.
Затем вы можете использовать его так же, как и вы:
router.get('/', (req, res, next) => {
scan().then(data => res.render('list', {
title: 'List',
data: data
})).catch(next);
});
К вашему сведению, для модуля fs
существует более новый (все еще экспериментальный) API, основанный на обещаниях.Вы можете использовать это следующим образом:
const path = require('path');
const fsp = require('fs').promises;
async function scan2(directoryName = './data', results = []) {
let files = await fsp.readdir(directoryName, {withFileTypes: true});
for (let f of files) {
let fullPath = path.join(directoryName, f.name);
if (f.isDirectory()) {
await scan2(fullPath, results);
} else {
results.push(fullPath);
}
}
return results;
}
Обратите внимание, что эта новая версия также использует новую опцию withFileTypes
, которая избавляет от необходимости вызывать stat()
для каждого файла.