在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