我尝试用dirs推送用户数组。但是此后,dir
属性在console.log语句中仍为空。
有想法吗?我知道我可以使用同步功能,但朋友告诉我,同步功能阻止了所有其他的事情发生。
router.get('/', function(req, res, next) {
const db = req.db;
const query = "SELECT * FROM users";
const users = [];
db.query(query, (error, results, fields) => {
for(let i = 0; i < results.length ; i++){
users.push(results[i]);
users[i].dir = [];
fs.readdir(path.join(__dirname,'..', 'userdata', results[i].username), (err, entries) => {
users[i].dir.push(entries[i]);
});
}
console.log(users);
res.render("admin", {
user: req.session.user,
dbUsers: users,
});
});
});
所以我刚刚更新了我的代码。但它也不起作用。
答案 0 :(得分:1)
正如@jfriend00所提到的,你需要研究异步操作。
我使用promises为异步调用重构了你的代码。你可以通过使用await来使它更容易阅读。
const queryUsers = (db) => new Promise ((resolve, reject) => {
const query = "SELECT * FROM users";
db.query(query, (error, results, fields) => {
if (error) {
return reject(error);
}
resolve(results);
});
});
const getUserFiles = username => new Promise((resolve, reject) => {
fs.readdir(path.join(__dirname,'..', 'userdata', username), (err, entries) => {
if (err) {
return reject(err);
}
resolve(entries);
});
});
const getUsersFiles = users => Promise.all(
users.map(user => getUserFiles(user.username)
.then(files => ({ ...user, dir: files })))
);
router.get('/', function(req, res, next) {
queryUsers(req.db)
.then(getUsersFiles)
.then(users => {
console.log(users);
res.render("admin", {
user: req.session.user,
dbUsers: users,
});
});
});
答案 1 :(得分:0)
fs.readdir
是异步函数,这意味着循环不会等到readdir
函数完成然后继续下一次迭代,尝试使用fs.readdirSync
使其同步,或者您可以使用async模块:
for(let i = 0; i < results.length ; i++){
users.push(results[i]);
let entries = fs.readdirSync(path.join(__dirname,'..', 'userdata', results[i].username));
users[i].dir = entries;
}
Async module解决方案:
async.eachOf( results, function(user, i, next) {
users.push(user);
fs.readdir(path.join(__dirname,'..', 'userdata', user.username), (err, entries) => {
// if error pass it to the last callback
if (err) return next(err);
user.dir = entries;
// iteration done
next();
});
}, function (err) {
// this function is executed only when all iteration done
if (err) {
throw err;
return res.send('error occured');
}
res.render("admin", {
user: req.session.user,
dbUsers: users,
});
});
答案 2 :(得分:-1)
你可以在这一行i
中调出users[i].dir.push(entries[i]);
的值吗?我猜每次都是最大编号项目+1,因为fs.readdir
调用是异步的,i
的值与预期的不匹配。尝试在这样的闭包中使用一个值。创建闭包时,i
的值将作为idx
保存到闭包中。
for(let i = 0; i < results.length ; i++){
(idx => {
users.push(results[idx]);
users[idx].dir = [];
fs.readdir(path.join(__dirname,'..', 'userdata', results[i].username), (err, entries) => {
users[idx].dir.push(entries[idx]);
});
})(i);
}