在forEach之后发送响应

(请注意,这不是两个类似标题的问题的重复,这两个问题使用mongoose,而答案仅适用于Mongoose查询)

我有一个目录列表,每个目录都包含一个文件。 我想返回一个JSON列表与每个这些文件的内容。 我可以加载文件没有问题,但因为我循环与forEach数组,我的空响应发送之前,我已经实际加载的文件的内容:

 function getInputDirectories() { return fs.readdirSync(src_path).filter(function(file) { return fs.statSync(path.join(src_path, file)).isDirectory(); }); } router.get('/list', function(req, res, next) { var modules = []; var input_dirs = getInputDirectories(); input_dirs.forEach(function(dir) { path = __dirname+'/../../modules/input/'+dir+'/module.json' fs.readFile(path, 'utf8', function(err, data) { modules.push(data); }); }); res.status(200).json(modules); }); 

我怎样才能确保我只发送modules数组一旦完全加载,即:一旦forEach完成。

由于fs.readFile是asynchronous的,所以你的行为很可能是预期的行为。

你需要做的是当所有模块被读取时返回你的模块。 你可以在fs.readFile做到这fs.readFile

据我所知,你可以通过input_dirs.length获得目录input_dirs.length (因为我猜getInputDirectories()正在返回一个数组)。 现在,您需要某种计数器来帮助您了解是否已经读取了最后一个目录,如果是,则返回模块。 像这样的东西应该工作:

 router.get('/list', function(req, res, next) { var modules = []; var input_dirs = getInputDirectories(); var c = 0; input_dirs.forEach(function(dir) { path = __dirname+'/../../modules/input/' + dir + '/module.json' fs.readFile(path, 'utf8', function(err, data) { c++; modules.push(data); if(c == input_dirs.length) { return res.status(200).json(modules); } }); }); }); 

我build议你使用Promise,例如:

 var Promise = require('bluebird'); router.get('/list', function(req, res, next) { var modules = []; var input_dirs = getInputDirectories(); // 'each' will try to fulfill all promises, if one fails, it returns a // failed promise. return Promise.each(input_dirs, function(dir){ path = __dirname+'/../../modules/input/'+dir+'/module.json'; return new Promise(function(resolve, reject){ fs.readFile(path, 'utf8', function(err, data) { if (err) return reject(err); return resolve(data); }); }); }).then(function(modules){ return res.status(200).json(modules); }) .catch(function(err){ if (err) { //handle error } }); }); 

这样,一旦你履行了你的承诺,你就可以移动一个。

而不是fs.readFile使用fs.readFileSync